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

2024-04-17
16:19
Few additions to release notes Leaf check-in: 811ffd1e5e user: jan.nijtmans tags: trunk, main
15:42
Add pkgs8 directories to git/fossil ignore files check-in: 7a4d7f7cb9 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
compat/zlib/contrib/dotzlib/DotZLib/UnitTests.cs

compat/zlib/contrib/vstudio/readme.txt
compat/zlib/contrib/vstudio/*/zlib.rc

compat/zlib/contrib/vstudio/*/*.sln

compat/zlib/win32/*.txt
compat/zlib/win64/*.txt

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


>

>


>



<









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

Changes to .fossil-settings/encoding-glob.

1
2
3
4
5
6
7
8
9
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
<







<

1
2
3
4
5
6
7


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

Changes to .fossil-settings/ignore-glob.

20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
*/config.status
*/tclConfig.sh
*/tclsh*
*/tcltest*
*/versions.vc
*/version.vc
*/libtcl.vfs
*/libtcl_*.zip

html
libtommath/bn.ilg
libtommath/bn.ind
libtommath/pretty.build
libtommath/tommath.src
libtommath/*.log
libtommath/*.pdf







|
>







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
*/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
libtommath/etc/*
libtommath/demo/*
libtommath/*.out
libtommath/*.tex
macosx/configure
unix/autoMkindex.tcl
unix/dltest.marker

unix/dltest/*.bundle
unix/dltest/*.dll
unix/dltest/*.dylib

unix/dltest/*.o
unix/dltest/*.sl
unix/dltest/*.so
unix/tcl.pc
unix/tclIndex
unix/Tcl-Info.plist
unix/Tclsh-Info.plist

unix/pkgs/*
win/Debug*
win/Release*
win/*.manifest

win/pkgs/*
win/coffbase.txt
win/tcl.hpj
win/nmakehlp.out
win/nmhlp-out.txt







>



>







>




>





44
45
46
47
48
49
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
*.svg text
*.ts text
*.tcl text
*.test text

# Declare files that will always have CRLF line endings on checkout.
*.bat 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







>







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


|
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-lang.org](https://core.tcl-lang.org/tcl/tktnew); please post them there.

Changes to .github/PULL_REQUEST_TEMPLATE.md.

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.


|
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-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
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 all
        timeout-minutes: 5
      - name: Build Test Harness
        run: |
          make tcltest
        timeout-minutes: 5
      - 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
name: macOS
on:
  push:
    branches:
    - "main"
    - "core-8-branch"
    - "core-8-6-branch"
    tags:
    - "core-**"
permissions:
  contents: read
jobs:
  xcode:
    runs-on: macos-11
    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 all
        env:
          CFLAGS: -arch x86_64 -arch arm64
        timeout-minutes: 15
      - name: Run Tests
        run: make test styles=develop
        env:
          ERROR_ON_FAILURES: 1
          MAC_CI: 1
        timeout-minutes: 15
  clang:
    runs-on: macos-11
    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 all tcltest
        env:
          CFLAGS: -arch x86_64 -arch arm64
        timeout-minutes: 15
      - 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
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: 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-11
    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 tclsh
          make 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: 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: 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
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 all
        timeout-minutes: 5
      - name: Build Test Harness
        run: make tcltest
        timeout-minutes: 5
      - 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
config.status
config.status.lineno
html
manifest.uuid
_FOSSIL_
*/tclConfig.sh
*/tclsh*
*/tcltest*
*/versions.vc
*/version.vc
*/libtcl.vfs
*/libtcl_*.zip

libtommath/bn.ilg
libtommath/bn.ind
libtommath/pretty.build
libtommath/tommath.src
libtommath/*.log
libtommath/*.pdf
libtommath/*.pl







|



|
>







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
*/versions.vc
*/version.vc
*/libtcl.vfs
*/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
libtommath/etc/*
libtommath/demo/*
libtommath/*.out
libtommath/*.tex
macosx/configure
unix/autoMkindex.tcl
unix/dltest.marker

unix/tcl.pc
unix/tclIndex

unix/pkgs/*
win/Debug*
win/Release*
win/*.manifest

win/pkgs/*
win/coffbase.txt
win/tcl.hpj
win/nmakehlp.out
win/nmhlp-out.txt







>


>




>





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

Changes to .travis.yml.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 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"







<
<
<
<
<
<
<







16
17
18
19
20
21
22







23
24
25
26
27
28
29
# Testing on Linux GCC
    - name: "Linux/GCC/Shared"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix







    - name: "Linux/GCC/Shared: NO_DEPRECATED"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
        - CFGOPT="CFLAGS=-DTCL_NO_DEPRECATED=1"
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    - 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:







<
<
<
<
<
<
<
<







44
45
46
47
48
49
50








51
52
53
54
55
56
57
    - name: "Linux/GCC/Mem-Debug"
      os: linux
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
        - CFGOPT="--enable-symbols=mem"








# Newer/Older versions of GCC
    - name: "Linux/GCC 10/Shared"
      os: linux
      dist: focal
      compiler: gcc-10
      addons:
        apt:
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
        - 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: []







<
<
<
<
<
<
<
<







121
122
123
124
125
126
127








128
129
130
131
132
133
134
        - BUILD_DIR=macosx
      install: []
      script: *mactest
      addons:
        homebrew:
          packages:
            - libtommath








# Newer MacOS versions
    - name: "macOS/Clang/Xcode 12/Universal Apps/Shared"
      os: osx
      osx_image: xcode12u
      env:
        - BUILD_DIR=macosx
      install: []
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
    - 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:







<














|
|







|
|







190
191
192
193
194
195
196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
    - 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

        - 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 'CHECKS=nodep' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'CHECKS=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' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x64 '&&' nmake 'OPTS=static' '-f' makefile.vc test
    - name: "Windows/MSVC/Debug"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
    - 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:







|
|







|
|







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    - 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 'CHECKS=nodep' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'CHECKS=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' '-f' makefile.vc all tcltest
        - cmd.exe //C vcvarsall.bat x86 '&&' nmake 'OPTS=static' '-f' makefile.vc test
    - name: "Windows/MSVC-x86/Debug"
      os: windows
      compiler: cl
      env: *vcenv
      before_install: *vcpreinst
      install: []
      script:
311
312
313
314
315
316
317
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
    - 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







<



<
<
<
<
<
<
<







<
<
<
<
<
<
<
<
<







287
288
289
290
291
292
293

294
295
296







297
298
299
300
301
302
303









304
305
306
307
308
309
310
    - name: "Windows/GCC/Shared"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-64bit"
      before_install: &makepreinst

        - touch generic/tclStubInit.c generic/tclOOStubInit.c generic/tclOOScript.h
        - choco install -y make zip
        - cd ${BUILD_DIR}







    - 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/GCC/Static"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--enable-64bit --disable-shared"
      before_install: *makepreinst
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
# 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







<
<
<
<
<
<
<







<
<
<
<
<
<
<
<
<







325
326
327
328
329
330
331







332
333
334
335
336
337
338









339
340
341
342
343
344
345
# 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: NO_DEPRECATED"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="CFLAGS=-DTCL_NO_DEPRECATED=1"
      before_install: *makepreinst









    - name: "Windows/GCC-x86/Static"
      os: windows
      compiler: gcc
      env:
        - BUILD_DIR=win
        - CFGOPT="--disable-shared"
      before_install: *makepreinst
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
      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







<











363
364
365
366
367
368
369

370
371
372
373
374
375
376
377
378
379
380
      dist: focal
      compiler: gcc
      env:
        - BUILD_DIR=unix
      script:
        - make dist
before_install:

  - 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  <[email protected]>

	*** 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  <[email protected]>

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

2013-09-18  Donal Fellows  <[email protected]>

	Bump TclOO version to 1.0.1 for release.

2013-09-17  Donal Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-08-02  Donal Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-07-02  Jan Nijtmans  <[email protected]>

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

2013-06-27  Jan Nijtmans  <[email protected]>

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

2013-06-18  Jan Nijtmans  <[email protected]>

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

2013-06-17  Jan Nijtmans  <[email protected]>

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

2013-06-09  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-05-22  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-05-19  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

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

2013-05-16  Jan Nijtmans  <[email protected]>

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

2013-05-13  Jan Nijtmans  <[email protected]>

	* compat/zlib/*: Upgrade to zlib 1.2.8

2013-05-10  Donal K. Fellows  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-04-25  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-04-08  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>
	* 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  <[email protected]>

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

2013-03-19  Don Porter  <[email protected]>

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

2013-03-19  Jan Nijtmans  <[email protected]>

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

2013-03-18  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

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

2013-03-11  Don Porter  <[email protected]>

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

2013-03-06  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-02-26  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

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

2013-02-25  Don Porter  <[email protected]>

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

2013-02-23  Jan Nijtmans  <[email protected]>

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

2013-02-22  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-02-19  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]> for identifying the problem.

2013-02-08  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-01-23  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-01-17  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-01-13  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2013-01-08  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-12-22  Alexandre Ferrieux  <[email protected]>

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

2012-12-21  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

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

2012-12-14  Don Porter  <[email protected]>

	*** 8.6.0 TAGGED FOR RELEASE ***

	* changes: updates for 8.6.0

2012-12-13  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-12-11  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

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

2012-10-23  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

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

2012-10-06  Jan Nijtmans  <[email protected]>

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

2012-10-03  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	*** 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  <[email protected]>

	* 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  <[email protected]>

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

2012-08-20  Don Porter  <[email protected]>

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

2012-08-20  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

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

2012-08-15  Jan Nijtmans  <[email protected]>

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

2010-08-13  Stuart Cassoff  <[email protected]>

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

2012-08-13  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

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

2010-08-08  Stuart Cassoff  <[email protected]>

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

2012-08-08  Jan Nijtmans  <[email protected]>

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

2012-08-07  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-07-27  Jan Nijtmans  <[email protected]>

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

2012-07-25  Alexandre Ferrieux  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-07-19  Alexandre Ferrieux  <[email protected]>

	* 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  <[email protected]>

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

2012-07-16  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

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

2012-07-11  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

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

2012-07-10  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-07-03  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

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

2012-06-29  Harald Oehlmann <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-06-25  Don Porter  <[email protected]>

	* 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  <[email protected]>

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

2012-06-25  Jan Nijtmans  <[email protected]>

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

2012-06-23  Jan Nijtmans  <[email protected]>

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

2012-06-22  Reinhard Max  <[email protected]>

	* 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  <[email protected]>

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

2012-06-11  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-05-31  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-05-29  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* {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  <[email protected]>

	* 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  <[email protected]>

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

2012-05-03  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-04-28  Alexandre Ferrieux  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

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

2012-04-26  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	IMPLEMENTATION OF TIP#396.

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

2012-04-02  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-03-27  Donal K. Fellows  <[email protected]>

	IMPLEMENTATION OF TIP#395.

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

2012-03-27  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-03-11  Donal K. Fellows  <[email protected]>

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

2012-03-08  Donal K. Fellows  <[email protected]>

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

2012-03-07  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

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

2012-03-04  Jan Nijtmans  <[email protected]>

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

2012-03-02  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

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

2012-02-23  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

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

2012-02-16  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-02-06  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

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

2012-02-02  Don Porter  <[email protected]>

	* 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  <[email protected]>

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

2012-01-30  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-01-17  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2012-01-09  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-12-11  Jan Nijtmans  <[email protected]>

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

2011-12-07  Jan Nijtmans  <[email protected]>

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

2011-11-30  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-11-22  Donal K. Fellows  <[email protected]>

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

2011-11-22  Jan Nijtmans  <[email protected]>

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

2011-11-20  Joe Mistachkin  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-11-11  Alexandre Ferrieux  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

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

2011-10-11  Jan Nijtmans  <[email protected]>

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

2011-10-09  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-10-03  Venkat Iyer <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-09-27  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-09-22  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-09-21  Andreas Kupries  <[email protected]>

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

2011-09-20  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

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

2011-09-16  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-09-11  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

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

2011-09-02  Don Porter  <[email protected]>

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

2011-09-01  Alexandre Ferrieux  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-08-29  Don Porter  <[email protected]>

	* generic/tclIORTrans.c: Leak of ReflectedTransformMap.

2011-08-27  Don Porter  <[email protected]>

	* 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  <[email protected]>

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

2011-08-19  Don Porter  <[email protected]>

	* 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  <[email protected]>

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

2011-08-18  Alexandre Ferrieux  <[email protected]>

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

2011-08-18  Jan Nijtmans  <[email protected]>

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

2011-08-17  Alexandre Ferrieux  <[email protected]>

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

2011-08-17  Alexandre Ferrieux  <[email protected]>

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

2011-08-17  Don Porter  <[email protected]>

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

2011-08-16  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-08-15  Jan Nijtmans  <[email protected]>

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

2011-08-14  Jan Nijtmans  <[email protected]>

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

2011-08-12  Don Porter  <[email protected]>

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

2011-08-12  Donal K. Fellows  <[email protected]>

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

2011-08-10 Alexandre Ferrieux  <[email protected]>

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

2011-08-09 Alexandre Ferrieux  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-08-09  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-08-06  Kevin B, Kenny  <[email protected]>

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

2011-08-05  Kevin B. Kenny  <[email protected]>

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

2011-08-05  Don Porter  <[email protected]>

	*** 8.6b2 TAGGED FOR RELEASE ***

	* changes:	Updates for 8.6b2 release.

2011-08-05  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

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

2011-08-04  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-08-02  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-07-28  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-07-19  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-07-18  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

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

2011-07-12  Don Porter  <[email protected]>

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

2011-07-11  Joe Mistachkin  <[email protected]>

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

2011-07-08  Donal K. Fellows  <[email protected]>

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

2011-07-07  Miguel Sofer  <[email protected]>

	* generic/tclBasic.c: Add missing INT2PTR

2011-07-03  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* generic/tclLink.c:	[Bug 3317466]: Prevent multiple links to a
	single Tcl variable when calling Tcl_LinkVar().

2011-06-13  Don Porter  <[email protected]>

	* generic/tclStrToD.c:  [Bug 3315098]: Mem leak fix from Gustaf
	Neumann.

2011-06-08  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c: Using the two free data elements in NRCommand to
	store objc and objv - useful for debugging.

2011-06-01  Jan Nijtmans  <[email protected]>

	* generic/tclUtil.c:   Fix for [Bug 3309871]: Valgrind finds: invalid
	read in TclMaxListLength().

2011-05-31  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* library/tzdata/Africa/Cairo: Update to Olson tzdata2011g

2011-05-24  Donal K. Fellows  <[email protected]>

	* library/msgcat/msgcat.tcl (msgcat::mcset, msgcat::mcmset): Remove
	some useless code; [dict set] builds dictionary levels for us.

2011-05-17  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclLoad.c (TclGetLoadedPackages): Convert to use Tcl_Obj API
	for result generation.

2011-05-07  Miguel Sofer  <[email protected]>

	* generic/tclInt.h: Fix USE_TCLALLOC so that it can be enabled without
	* unix/Makefile.in: editing the Makefile.

2011-05-05  Don Porter  <[email protected]>

	* generic/tclListObj.c:	Stop generating string rep of dict when
	converting to list.  Tolerate NULL interps more completely.

2011-05-03  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclConfig.c:	Reduce internals access in the implementation
	of [<foo>::pkgconfig list].

2011-04-18  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/string.test:	Test for [Bug 3285472]. Not buggy in trunk.

2011-04-12  Venkat Iyer <[email protected]>

	* library/tzdata/Atlantic/Stanley: Update to Olson tzdata2011f

2011-04-12  Miguel Sofer  <[email protected]>

	* generic/tclBasic.c: Fix for [Bug 2440625], kbk's patch

2011-04-11  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinPort.h: Fix for [Bug 3280043]: win2k: unresolved DLL
	* win/configure.in: imports.
	* win/configure

2011-04-06  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/init.tcl: TIP#131 implementation.

2011-03-31  Donal K. Fellows  <[email protected]>

	* generic/tclGetDate.y, generic/tclDate.c (TclClockOldscanObjCmd):
	More generation of errorCode information.

2011-03-28  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tcl.h (ckfree,etc.): Restored C++ usability to the memory
	allocation and free macros.

2011-03-24  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclObj.c: Exploit HAVE_FAST_TSD for the deletion context in
	TclFreeObj()

2011-03-22  Miguel Sofer  <[email protected]>

	* generic/tclThreadAlloc.c: Simpler initialization of Cache under
	HAVE_FAST_TSD, from mig-alloc-reform.

2011-03-21  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompExpr.c (ParseExpr): Generate errorCode information on
	failure to parse expressions.

2011-03-17  Jan Nijtmans  <[email protected]>

	* generic/tclMain.c: [Patch 3124683]: Reorganize the platform-specific
	stuff in (tcl|tk)Main.c.

2011-03-16  Jan Nijtmans  <[email protected]>

	* generic/tclCkalloc.c: [Bug 3197864]: Pointer truncation on Win64
	TCL_MEM_DEBUG builds.

2011-03-16  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: remove TEBCreturn()

2011-03-12  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinFile.c: [Bug 3185609]: File normalization corner case
	of ... broken with -DUNICODE

2011-03-11  Donal K. Fellows  <[email protected]>

	* tests/unixInit.test: Make better use of tcltest2.

2011-03-10  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* tests/incr.test: Update more of the test suite to use Tcltest 2.

2011-03-09  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* tests/dstring.test, tests/init.test, tests/link.test: Update more of
	the test suite to use Tcltest 2.

2011-03-08  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclAssembly.c, tests/assemble.test: Migrate to use a style
	more consistent with the rest of Tcl.

2011-03-06  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* generic/tclParse.c (TclParseBackslash): [Bug 3200987]: Correct
	* tests/parse.test:	trunction checks in \x and \u substitutions.

2011-03-05  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/RegExp.3: [Bug 3165108]: Corrected documentation of description
	of subexpression info in Tcl_RegExpInfo structure.

2011-01-25  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Fix crash when multiple -index
	options are used. Simplified memory handling logic.

2010-12-20  Jan Nijtmans  <[email protected]>

	* win/tclWin32Dll.c:    [Patch 3059922]: fixes for mingw64 - gcc4.5.1
	tdm64-1: completed for all environments.

2010-12-20  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in:  Remove unwanted/obsolete 'ddd' target.

2010-12-17  Stuart Cassoff  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in:  [Bug 2446711]: Remove 'allpatch' target.

2010-12-17  Stuart Cassoff  <[email protected]>

	* unix/Makefile.in:  [Bug 2537626]: Use 'rpmbuild', not 'rpm'.

2010-12-16  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* generic/tcl.h: [Bug 3137454]: Tcl CVS HEAD does not build on GCC 3.

2010-12-14  Reinhard Max  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tcl.m4: Better building on OpenBSD.
	* unix/configure: (autoconf-2.59)

2010-12-10  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBinary.c:  [Bug 3129448]: Possible over-allocation on
	* generic/tclCkalloc.c: 64-bit platforms.
	* generic/tclTrace.c:

2010-12-05  Jan Nijtmans  <[email protected]>

	* unix/tcl.m4: [Patch 3116490]: Cross-compile support for unix
	* unix/configure: (autoconf-2.59)

2010-12-03  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/chanio.test: Converted many tests to tcltest2 by marking the
	setup and cleanup parts as such.

2010-11-19  Jan Nijtmans  <[email protected]>

	* win/tclWin32Dll.c: Fix gcc warnings: unused variable 'registration'
	* win/tclWinChan.c:
	* win/tclWinFCmd.c:

2010-11-18  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* doc/file.n: [Bug 3111298]: Typofix.

	* tests/oo.test: [Bug 3111059]: Added testing that neatly trapped this
	issue.

2010-11-18  Miguel Sofer  <[email protected]>

	* generic/tclNamesp.c: [Bug 3111059]: Fix leak due to bad looping
	construct.

2010-11-17  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* changes:	Updates for 8.6b2 release.

2010-11-09  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in:	[Patch 3101127]: Installer Improvements.
	* unix/install-sh:

2010-11-04  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* changes:	Updates for 8.6b2 release.  (Thanks Andreas Kupries)

2010-11-03  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/tzdata/Asia/Hong_Kong:
	* library/tzdata/Pacific/Apia:
	* library/tzdata/Pacific/Fiji:   Olson's tzdata2010o.

2010-10-29  Alexandre Ferrieux  <[email protected]>

	* generic/tclTimer.c:	[Bug 2905784]: Stop small [after]s from
				wasting CPU while keeping accuracy.

2010-10-28  Kevin B. Kenny  <[email protected]>

	[dogeen-assembler-branch]
	* generic/tclAssembly.c:
	* tests/assembly.test (assemble-31.*): Added jump tables.

2010-10-28  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixSock.c (TcpGetOptionProc): Prevent crash if interp is
	* win/tclWinSock.c (TcpGetOptionProc):   NULL (a legal situation).

2010-10-26  Reinhard Max  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/info.n:           Document [info errorstack] faithfully.

2010-10-16  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinThrd.h: (removed) because it is just empty en used nowhere
	* win/tcl.dsp

2010-10-12  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixSock.c (CreateClientSocket): [Bug 3084338]: Fix a
	memleak and refactor the calls to freeaddrinfo().

2010-10-11  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: Fix overallocation of exec stack in TEBC (due
	to mixing numwords and numbytes)

2010-10-08  Jan Nijtmans  <[email protected]>

	* generic/tclIOSock.c: On Windows, use gai_strerrorA

2010-10-06  Don Porter  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* generic/tclExecute.c (TEBCresume): [Bug 3079830]: Added invalidation
	of string representations of dictionaries in some cases.

2010-10-01  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[dogeen-assembler-branch]

	* tests/assemble.test:
	* generic/tclAssemble.h:
	* generic/tclAssemble.c:  Added listIn, listNotIn, and dictGet.

2010-09-30  Kevin B. Kenny  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* unix/configure:	Re-generate with autoconf-2.59
	* win/configure:
	* generic/tclMain.c:	Make compilable with -DUNICODE as well

2010-09-28  Reinhard Max  <[email protected]>

	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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclOOMethod.c (ProcedureMethodVarResolver): avoid code
	duplication, let the runtime var resolver call the compiled var
	resolver.

2010-09-26  Kevin B. Kenny  <[email protected]>

	[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   <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclAppInit.c:  Make compilable with -DUNICODE (not activated
	* win/tclAppInit.c:   yet), many clean-ups in comments.

2010-09-22  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/file.n (file readlink): [Bug 3070580]: Typofix.

2010-09-18  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in:	Revise `make dist` target to tolerate the
	case of zero bundled packages.

2010-09-15  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWin32Dll.c: Partly revert yesterday's change, to make it work
	on VC++ 6.0 again.

2010-09-10  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tcl.m4: Applied patch by Jeff fixing issues with the manifest
	handling on Win64.
	* win/configure: Regenerated.

2010-08-30  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/dict.n: [Bug 3046999]: Corrected cross reference to array
	manpage to refer to (correct) existing subcommand.

2010-08-26  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/tzdata/Africa/Cairo:
	* library/tzdata/Asia/Gaza: Olson's tzdata2010l.

2010-08-22  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* doc/linsert.n: [Bug 3045123]: Make description of what is actually
	happening more accurate.

2010-08-21  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* doc/Method.3:   Fix definition of Tcl_MethodType.

2010-08-19  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/safe.tcl (AliasGlob): [Bug 3004191]: Restore safe [glob] to
	working condition.

2010-08-15  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (TclNRYieldToObjCmd):
	* tests/coroutine.test: Fixed bad copypasta snafu. Thanks to Andy Goth
	for finding the bug.

2010-08-10  Jeff Hobbs  <[email protected]>

	* generic/tclUtil.c (TclByteArrayMatch): Patterns may not be
	null-terminated, so account for that.

2010-08-09  Don Porter  <[email protected]>

	* changes:	Updates for 8.6b2 release.

2010-08-04  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIORChan.c: [Bug 3034840]: Fixed reference counting in
	* generic/tclIORTrans.c: InvokeTclMethod and callers.
	* tests/ioTrans.test:

2010-08-03  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c: Correcting bad port of [Bug 3037525] fix

2010-07-28  Miguel Sofer  <[email protected]>

	* generic/tclVar.c: [Bug 3037525]: Lose fickle optimisation in
	TclDeleteVars (used for runtime-created locals) that caused crash.

2010-07-29  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* doc/http.n: Corrected description of location of one of the entries
	in the state array.

2010-07-24  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c: Added more errorCode setting.

2010-07-15  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.decls:  [Bug 803489]: Tcl_FindNamespace problem in
	* generic/tclIntDecls.h: the Stubs table
	* generic/tclStubInit.c:

2010-07-02  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/mathop.n: [Bug 3023165]: Fix typo that was preventing proper
	rendering of the exclusive-or operator.

2010-06-28  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdIL.c (Tcl_LsetObjCmd): [Bug 3019351]: Corrected wrong
	args message.

2010-06-21  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.h: [Patch 3008541]: Order of TIP #348 fields in
	Interp structure

2010-05-28  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclStrToD.c: [Bug 2996549]: Failure in expr.test on Win32

2010-05-17  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclPkg.c:   Unnecessary type casts, see [Patch 2997087]

2010-05-04  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/coroutine.test: testing coroutine arguments after [yield]:
	check that only 0/1 allowed

2010-04-30  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): Rearrange location of an
	assignment to shorten the object code.

2010-04-27  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c:    Add unsupported [yieldm] command. Credit
	* generic/tclInt.h:      Lars Hellstrom for the basic idea.

2010-04-24  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixPort.h: [Bug 2991415]: tclport.h #included before
	limits.h

2010-04-22  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* generic/tclTest.c:  Use function prototypes from the FS API.
	* compat/zlib/*:      Upgrade to zlib 1.2.5

2010-04-19  Donal K. Fellows  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): Improve commenting and
	reduce indentation for the Invocation Block.

2010-04-18  Donal K. Fellows  <[email protected]>

	* doc/unset.n: [Bug 2988940]: Fix typo.

2010-04-15  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* doc/try.n: [Bug 2987551]: Fix typo.

2010-04-14  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/catch.n, doc/info.n, doc/return.n: Formatting.

2010-04-06  Donal K. Fellows  <[email protected]>

	* doc/Load.3: Minor corrections of formatting and cross links.

2010-04-06  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* unix/tcl.m4:            Only test for -visibility=hidden with gcc
	                          (Second remark in [Bug 2976508])
	* unix/configure:         regen

2010-03-29  Don Porter  <[email protected]>

	* generic/tclStringObj.c:       Fix array overrun in test format-1.12
	caught by valgrind testing.

2010-03-27  Jan Nijtmans  <[email protected]>

	* generic/tclInt.h:	[FRQ 2974744]: share exception codes
	* generic/tclResult.c:	(ObjType?)
	* generic/tclCmdMZ.c:
	* generic/tclCompCmdsSZ.c:

2010-03-26  Jan Nijtmans  <[email protected]>

	* generic/tclExecute.c: [Bug 2976508]: Tcl HEAD fails on HP-UX

2010-03-25  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdMZ.c:	[Bug 2973361]: Revised fix for computing
	indices of script arguments to [try].

2010-03-23  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompCmdsSZ.c (TclCompileThrowCmd): Added compilation for
	the [throw] command.

2010-03-18  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/makefile.vc: [Bug 2967340]: Static build was failing.
	* win/.cvsignore:

2010-03-10  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIORChan.c: [Bug 2936225]: Thanks to Alexandre Ferrieux
	* doc/refchan.n:    <[email protected]> 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* unix/tcl.m4:     [FRQ 2959069]: Support for -fvisibility=hidden
	* unix/configure   (regenerated with autoconf-2.59)

2010-03-01  Alexandre Ferrieux  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclStubInit.c: [Bug 2959713]: Link error with gcc 4.1

2010-02-27  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/regexp.test: Add test cases back ported from Jacl regexp work.

2010-02-21  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompCmds.c (TclCompileStringLenCmd): Make [string length]
	of a constant string be handled better (i.e., handle backslashes too).

2010-02-19  Stuart Cassoff  <[email protected]>

	* tcl.m4: Correct compiler/linker flags for threaded builds on
	OpenBSD.
	* configure: (regenerated).

2010-02-19  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.h: Change order of various struct members,
	fixing potential binary incompatibility with Tcl 8.5

2010-02-16  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/list.test: Add tests for explicit \0 in a string argument to
	the list command.

2010-02-11  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tools/genStubs.tcl: Remove dependency on 8.5+ idiom "in" in
	expressions.

2010-02-08  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompCmds.c (TclCompileErrorCmd): Added compilation of the
	[error] command. No new bytecodes.

2010-02-05  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c (ArrayUnsetCmd): More corrections.

2010-02-02  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/proc.n: [Bug 1970629]: Define a bit better what the current
	namespace of a procedure is.

2010-01-22  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): Improve error code
	generation from some of the tailcall-related bits of TEBC.

2010-01-21  Miguel Sofer  <[email protected]>

	* generic/tclCompile.h: [Bug 2910748]: NRE-enable direct eval on BC
	* generic/tclExecute.c: spoilage.
	* tests/nre.test:

2010-01-19  Donal K. Fellows  <[email protected]>

	* doc/dict.n: [Bug 2929546]: Clarify just what [dict with] and [dict
	update] are doing with variables.

2010-01-18  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tcl.m4 (SC_CONFIG_CFLAGS): [Bug 1636685]: Use the configuration
	for modern FreeBSD suggested by the FreeBSD porter.

2010-01-03  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/init.tcl (unknown): [Bug 2824981]: Fix infinite recursion of
	::unknown when [set] is undefined.

2009-12-29  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBinary.c:	[Bug 2922555]: Handle completely invalid input
	* tests/binary.test:	to the decode methods.

2009-12-28  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* doc/namespace.n (SCOPED SCRIPTS): [Bug 2921538]: Updated example to
	not be quite so ancient.

2009-12-25  Jan Nijtmans  <[email protected]>

	* generic/tclCmdMZ.c:      CONST -> const
	* generic/tclParse.c

2009-12-23  Donal K. Fellows  <[email protected]>

	* library/safe.tcl (AliasSource, AliasExeName): [Bug 2913625]: Stop
	information about paths from leaking through [info script] and [info
	nameofexecutable].

2009-12-23  Jan Nijtmans  <[email protected]>

	* unix/tcl.m4:		Install libtcl8.6.dll in bin directory
	* unix/Makefile.in:
	* unix/configure:	(regenerated)

2009-12-22  Donal K. Fellows  <[email protected]>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): [Bug 2918962]: Stop crash when
	-index and -stride are used together.

2009-12-21  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tools/tcltk-man2html.tcl (long-toc, cross-reference): [FRQ 2897296]:
	Added cross links to sections within manual pages.

2009-12-11  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c: Ensure right lifetime of varFrame's (objc,objv)
	for coroutines.

	* generic/tclExecute.c: Code regrouping

2009-12-09  Donal K. Fellows  <[email protected]>

	* generic/tclBasic.c: Added some of the missing setting of errorcode
	values.

2009-12-08  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c (TclStackFree): Improved panic msg.

2009-12-08  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c: [Patch 2910056]: Add ::tcl::unsupported::yieldTo
	* generic/tclInt.h:

2009-12-07  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/Tcl.n: [Bug 2901433]: Improved description of expansion to
	mention that it is using list syntax.

2009-11-27  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclThreadTest.c (NewTestThread): [Bug 2901803]: Fix small
	error in function naming which blocked a threaded test build.

2009-11-19  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* unix/tclAppInit.c:	[Bug 2883850, 2900542]: Repair broken build of
	* win/tclAppInit.c:	the tcltest executable.

2009-11-19  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinDde.c: Avoid gcc compiler warning by explicitly casting
	DdeCreateStringHandle argument.

2009-11-12  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* generic/tclClock.c (TclClockInit):    Do not create [clock] support
	commands in safe interps.

2009-11-11  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/README: [bug 2459744]: Removed outdated Msys + Mingw info.

2009-11-09  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/object.n (DESCRIPTION): Substantive revision to make it clearer
	what the fundamental semantics of an object actually are.

2009-11-01  Joe Mistachkin  <[email protected]>

	* 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  <[email protected]>

	* doc/Eval.3, doc/Cancel.3: Move TIP#285 routines out of Eval.3 into
	their own manpage.

2009-10-31  Donal K. Fellows  <[email protected]>

	* generic/tclBasic.c (ExprRoundFunc): [Bug 2889593]: Correctly report
	the expected number of arguments when generating an error for round().

2009-10-30  Pat Thoyts  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclPathObj.c: [Bug 2884203]: Missing refcount on cached
	normalized path caused crashes.

2009-10-27  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in:	Remove $(PACKAGE).* and prototype from the
	`make distclean` target.  Completes 2009-10-20 commit.

2009-10-24  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>.

2009-10-22  Donal K. Fellows  <[email protected]>

	* generic/tclOOBasic.c (TclOO_Object_VarName): [Bug 2883857]: Allow
	the passing of array element names through this method.

2009-10-21  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>.

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/tzdata/Africa/Cairo:
	* library/tzdata/Asia/Gaza:
	* library/tzdata/Asia/Karachi:
	* library/tzdata/Pacific/Apia:	Olson's tzdata2009n.

2009-09-29  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/error.test (error-15.8.*):	Coverage tests illustrating
	flaws in the propagation of return options by [try].

2009-09-26  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* doc/namespace.n: the description of [namespace unknown] failed
	to mention [namespace path]: fixed. Thx emiliano.

2009-09-21  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile.c:	Correct botch in the conversion of
	Tcl_SubstObj().  Thanks to Kevin Kenny for detection and report.

2009-09-17  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* generic/tclObj.c:   Extended ::tcl::unsupported::representation.

2009-09-11  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclParse.c:	[Bug 2850901]: Corrected line counting error
	* tests/into.test:	in multi-command script substitutions.

2009-09-07  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclStringObj.c:       [Bug 2845535]: A few more string
	overflow cases in [format].

2009-08-25  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclFileName.c: Correct regression in [Bug 2837800] fix.
	* tests/fileName.test:

2009-08-20  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdAH.c (TclNRForObjCmd, etc.): [Bug 2823276]: Make [for]
	and [while] into NRE-safe commands, even when interpreted.

2009-08-18  Don Porter  <[email protected]>

	* generic/tclPathObj.c: [Bug 2837800]: Added NULL check to prevent
	* tests/fileName.test:  crashes during [glob].

2009-08-16  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* tests/coroutine.test: fix testfile cleanup

2009-08-02  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

2009-07-23  Joe Mistachkin  <[email protected]>

	* generic/tclNotify.c: [Bug 2820349]: Ensure that queued events are
	freed once processed.

2009-07-22  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/tzdata/Asia/Dhaka:
	* library/tzdata/Indian/Mauritius: Olson's tzdata2009k.

2009-07-20  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/zlib.test: [Bug 2818131]: Added tests and fixed a typo that
	broke [zlib push] for deflate format.

2009-07-09  Donal K. Fellows  <[email protected]>

	* compat/mkstemp.c (mkstemp): [Bug 2819227]: Use rand() for random
	numbers as it is more portable.

2009-07-05  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/oo.test (oo-19.1): [Bug 2811598]: Make more resilient.

2009-06-24  Pat Thoyts  <[email protected]>

	* tests/http11.test: [Bug 2811492]: Clean up procs after testing.

2009-06-18  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclStringObj.c: sprintf() -> Tcl_ObjPrintf() conversion.

2009-06-15  Reinhard Max  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/tzdata/Asia/Dhaka: New DST rule for Bangladesh. (Olson's
	tzdata2009i.)

2009-06-08  Donal K. Fellows  <[email protected]>

	* doc/copy.n: Fix error in example spotted by Venkat Iyer.

2009-06-02  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* tests/expr.test:      [Bug 2798543]: Added many tests demonstrating
	the broken cases.

009-05-30  Kevin B. Kenny  <[email protected]>

	* library/tzdata/Africa/Cairo:
	* library/tzdata/Asia/Amman: Olson's tzdata2009h.

2009-05-29  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* doc/expr.n: Fixed documentation of the right-associativity of
	the ** operator. (spotted by kbk)

2009-05-14  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (TclObjInvoke): [Bug 2486550]: Make sure that a
	null objProc is not used, use Tcl_NRCallObjProc instead.

2009-05-01  Jan Nijtmans  <[email protected]>

	* win/configure.in   Fix 64-bit detection for zlib on Win64
	* win/configure      (regenerated)

2009-04-28  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in: [Patch 2769530]: Don't chmod/exec installManPage.

2009-04-19  Pat Thoyts  <[email protected]>

	* 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  <[email protected]>

	* doc/chan.n, doc/close.n: Tidy up documentation of TIP #332.

2009-04-14  Kevin B. Kenny  <[email protected]>

	* library/tzdata/Asia/Karachi: Updated rules for Pakistan Summer
				       Time (Olson's tzdata2009f)

2009-04-11  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/StringObj.3: [Bug 2089279]: Corrected example so that it works
	on 64-bit machines as well.

2009-04-10  Pat Thoyts  <[email protected]>

	* tests/http.test: [Bug 26245326]: Added specific check for problem
	* tests/httpd: (return incomplete HTTP response header).

2009-04-08  Kevin B. Kenny  <[email protected]>

	* tools/tclZIC.tcl: Always emit files with Unix line termination.
	* library/tzdata: Olson's tzdata2009e

2009-04-09  Don Porter  <[email protected]>

	* library/http/http.tcl:	[Bug 26245326]: Handle incomplete
	lines in the "connecting" state. Thanks to Sergei Golovan.

2009-04-08  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/Alloc.3: [Bug 2556263]:	Size argument is "unsigned int".

2009-03-27  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/coroutine.n: [Bug 2152285]: Added basic documentation for the
	coroutine and yield commands.

2009-03-24  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c: [Bug 2502037]: NR-enable the handling of unknown
	commands.

2009-03-21  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/tailcall.n: Added documentation for tailcall command.

2009-03-18  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdMZ.c (TryPostBody): [Bug 2688063]: Extract information
	from list before getting rid of last reference to it.

2009-03-15  Joe Mistachkin  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (TclNRCoroutineObjCmd): fix Tcl_Obj leak.
	Diagnosis and fix thanks to GPS.

2009-03-09  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile.c: [Bug 2555129]: const compiler warning (as
	error) in tclCompile.c

2009-02-07  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinSock.c: [Bug 2446662]: Resync Win behavior on RST with
	that of unix (EOF).

2009-01-26  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* doc/zlib.n: Added a note that 'zlib push' is reversed by 'chan pop'.

2009-01-22  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* unix/tcl.m4: Corrected a typo ($(SHLIB_VERSION) should be
	${SHLIB_VERSION}).
	* unix/configure: Autoconf 2.59

2009-01-21  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* generic/tclStringObj.c: New fix for [Bug 2494093] replaces the
	flawed attempt committed 2009-01-09.

2009-01-19  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdMZ.c (Tcl_ThrowObjCmd):	Move implementation of [throw]
	* library/init.tcl (throw):		to C from Tcl.

2009-01-12  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclNamesp.c (NamespaceEnsembleCmd): [Bug 1558654]: Error out
	when someone gives wrong # of args to [namespace ensemble create].

2009-01-08  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdAH.c: Tidy up spacing and code style.

2009-01-03  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* changes: updated changes file
	* tools/tclSplash.bmp: updated to show 8.3

1999-12-21  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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. ([email protected])

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* {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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/aclocal.m4: Changed AIX-4.[2-9] check to AIX-4.[1-9] [Bug 1909]

1999-08-20  Jeff Hobbs  <[email protected]>

	* generic/tclPosixStr.c: fixed typo. [Bug 2592]

	* doc/*: fixed various nroff bugs in man pages. [Bug 2503 2588]

1999-08-19  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* /: 8.2.0 tagged for final release

1999-08-12  Scott Stanton  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinSerial.c: Applied patch from Petteri Kettunen to remove
	compiler warning.

1999-08-10  Scott Redman  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinInt.h: Remove function declarations in header that was
	moved to tclInt.decls file in previous changes.

1999-08-02  Scott Redman  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.decls: added declaractions necessary for the Tcl test
	code to work wth stubs. [Bug 2445]

1999-07-30  Scott Redman  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tools/tclSplash.bmp: Updated Windows installer bitmap to ready
	Tcl/Tk Version 8.2.

1999-07-26  Scott Redman  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* README: Small tweaks to clean up typos and wording.

1999-07-20  Melissa Hirschl  <[email protected]>

	* 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  <[email protected]>

	* library/http2.1/http.tcl: updated -useragent text to say version
	2.1.

1999-07-16  Scott Redman  <[email protected]>

	* 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  <[email protected]>

	* tools/tcl.wse.in: Fixed naming of target files for Windows.

1999-07-14  Jerry Peek  <[email protected]>

	* doc/re_syntax.n: Deleted sentence as suggested by Scott S.

1999-07-12  Jerry Peek  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/string.test:
	* generic/tclCmdMZ.c: Fixed bug in string range bounds checking code.

1999-07-08  Jennifer Hom  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/fconfigure.n: Clarified default buffering behavior for the
	standard channels. [Bug 2335]

1999-07-06  Scott Redman  <[email protected]>

	* win/tclWinSerial.c: New implementation of serial port driver from
	Rolf Shroedter ([email protected]) 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/reg.test:
	* generic/regexec.c: Fixed bugs in non-greedy quantifiers.

1999-06-23  Jerry Peek  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixThrd.c (TclpThreadCreate): Fixed memory leak where
	thread attributes were not being released. [Bug 2254]

1999-06-17  Scott Stanton  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclUtf.c (Tcl_UtfNcasecmp): Fixed incorrect computation of
	relative ordering. [Bug 2135]

1999-06-01  Scott Stanton  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdAH.c (Tcl_ForObjCmd): Fixed crash caused by failure to
	reset the result before evaluating the test expression.

1999-05-14  Bryan Surles  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/makefile.vc: Added encoding directory to install-libraries
	target.

1999-05-03  Scott Stanton  <[email protected]>

	* 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  <[email protected]>

	* Changed version to 8.1.1.

1999-04-30  Scott Stanton  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclLiteral.c (TclHideLiteral): Fixed so hidden literals get
	duplicated to avoid accidental sharing in the global object table.

1999-04-23  Scott Stanton  <[email protected]>

	* generic/tclStubInit.c:
	* tools/genStubs.tcl: Changed to avoid the need for forward
	declarations in stub initializers.

1999-04-23  Scott Stanton  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* Merged 8.1 back into the main trunk

1999-04-13  Scott Stanton  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclFileName.c:
	* generic/tclDecls.h:
	* generic/tcl.decls: Added CONST to Tcl_JoinPath and
	Tcl_TranslateFileName.

1999-03-29  Scott Redman  <[email protected]>

	* 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  <[email protected]>

	* win/makefile.bc: Removed makefile for Borland compiler, no longer
	supported.

1999-03-26  Scott Redman  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/reg.test:
	* generic/regc_color.c: Applied regexp bug fix from Henry Spencer.

1999-03-19  Scott Redman  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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 <[email protected]>. 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/.cvsignore: Removed 'configure' from the glob list now that it's
	included.

2000-11-03  Jeff Hobbs  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* win/tclConfig.sh.in (TCL_LIBS): Cleaned up unix-specific autoconf
	variables.

2000-07-11  Jeff Hobbs  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* doc/trace.n: minor doc cleanup

2000-09-06  André Pönitz <[email protected]>

	* doc/*.n: added or changed "SEE ALSO:" section

2000-09-06  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/man.macros: Tweaked tab settings for .SO (Standard Options)
	sections, based on suggestion from Peter Spjuth.

2000-08-24  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* generic/tclVar.c: Added check for non-arrays for [array statistics]
	command (patch from Mark Patton).

2000-08-19  David Gravereaux <[email protected]>

	* 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 <[email protected]>

	* win/.cvsignore (added): provides a cleaner build environment with
	graphical CVS clients.

2000-08-15  Eric Melski  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tclObj.c: r1.15 accidentally changed a global mutex name
	tclObjMutex to ObjMutex.  Put the correct name back.

2000-08-07  Eric Melski  <[email protected]>

	* 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  <[email protected]>

	* win/configure.in: TCL_STUB_LIB_FLAG should not include ${TCL_DBGX}
	in win/tclConfig.sh, fix that.

2000-07-25  David Gravereaux  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/msgcat.n: Added documentation about the selection of the default
	locale on Windows.

2000-07-23  Joe English  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* compat/string.h: Fixed function prototypes for strpbrk and strtok
	[Bug: 6020].

2000-07-17  David Gravereaux  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/package.n: Corrected information about [package forget]
	arguments [Bug: 5418].

2000-06-23  Eric Melski  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/RegExp.3: Replaced instances of "Tcl_GetRegExpInfo" with
	"Tcl_RegExpGetInfo", the correct name of the function [Bug: 5901].

2000-06-13  Eric Melski  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* generic/tclIndexObj.c (Tcl_GetIndexFromObjStruct): Corrected caching
	of the index ptr to account for offsets != sizeof(char *). [Bug: 5153]

2000-05-29  Sandeep Tamhankar <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>
	operating as proxy for David Gravereaux <[email protected]>

	* win/tclWinThrd.c (TclpInitLock, TclpMasterLock): Added missing
	initialization of joinLock.

2000-05-09  Eric Melski  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/set-old.test:
	* doc/array.n:
	* generic/tclVar.c: Added [array statistics] command [RFE: 4557]

2000-05-06  Andreas Kupries <[email protected]>
	operating as proxy for David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* unix/mkLinks:
	* doc/AddErrInfo.3: Added information about Tcl_LogCommandInfo
	[Bug: 1818].

2000-04-24  Eric Melski  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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 <[email protected]>

	* library/package.tcl (tclPkgUnknown): Fixed a typo in the Mac package
	search part of tclPkgUnknown.

2000-04-21  Sandeep Tamhankar <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/dde.n: corrected dde poke docs. [Bug: 4991]

2000-04-11  Eric Melski  <[email protected]>

	* win/tclWinPipe.c: Added "CONST" keyword to declaration of char
	*native in TclpCreateTempFile, to supress compiler warnings.

2000-04-10  Brent Welch <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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
	<[email protected]> 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* {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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixFCmd.c (SetGroupAttribute):
	* unix/tclUnixFCmd.c (SetOwnerAttribute): Added (uid_t) and (gid_t)
	casts to avoid compiler warnings.

2000-03-31  Eric Melski  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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	 <[email protected]>

	* 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 ([email protected])

2000-02-08  Eric Melski  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/package.test:
	* library/tclIndex:
	* library/package.tcl: Renamed ::package namespace to ::pkg.

2000-02-03  Eric Melski <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/init.tcl: Applied patch from rfe 1734 regarding auto_load
	errors not setting error message and errorInfo properly.

2000-02-01  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinSerial.c (SerialCheckProc): corrected time calculations to
	be unsigned. (schroedter)

2001-12-18  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* Applied [Bug 219311] on behalf of Rolf Schroedter
	<[email protected]> to prevent fcopy on serial ports
	from flooding the event queue.

2001-12-11  Miguel Sofer  <[email protected]>

	* doc/CrtInterp.3:
	* generic/tclBasic.c: docs and comments corrections. [Bug 493412]
	Bug & patch by Don Porter.

2001-12-14  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/Preserve.3: doc'd TCL_DYNAMIC use. [Patch 483989] (porter)

2001-12-12  Andreas Kupries  <[email protected]>

	* generic/tclIO.c (Tcl_GetsObj): Applied patch for [Bug 491341] as
	provided by Don Porter <[email protected]>. Fixes the
	assumption of having an empty Tcl_Obj to work with.

2001-12-11  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixPipe.c (TclpCreateProcess): Applied Don Porter's patch
	fixing [Bug 437489].

2001-12-10  Miguel Sofer  <[email protected]>

	* generic/tclEvent.c:
	* tests/event.test: fix background error reporting in the absence of a
	bgerror proc [Bug 219142].

2001-12-10  Don Porter <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/namespace.test: modified namespace-41.2, added 41.3
	{knownbug} after discussion with Don Porter and Kevin Kenny.

2001-11-29  Miguel Sofer  <[email protected]>

	* tests/namespace.test: added namespace-41.2, a simpler test for
	[Bug 231259]

2001-11-29  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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   <[email protected]>

	* win/tclWinFCmd.c: Fix a coredump in the filename normalizer code for
	Win95/98.

2001-11-27  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tclIntPlatDecls.h: 'make genstubs' after changes in
	2001-11-23 commit from Daniel Steffen.

2001-11-24  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: missing variable declaration under
	TCL_COMPILE_DEBUG.

2001-11-20  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* win/buildall.vc.bat:  Added useful comments.

2001-11-19  Miguel Sofer  <[email protected]>

	* tests/compile.test: added a test for bug [Bug 483309]

2001-11-19  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompCmds.c: patch for [Bug 483309] (petasis).

2001-11-16  Kevin B. Kenny  <[email protected]>

	* generic/tclListObj.c: removed a C++-style comment that was
	inadvertently left in the source code.

2001-11-16  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* doc/FileSystem.3:
	* doc/file.n:
	* doc/tcltest.n: converted use of \' to more reasonable format.

2001-11-10  Mo DeJong  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]> 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  <[email protected]>

	* 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	<[email protected]>

	* tests/var.test:
	* generic/tclVar.c: Corrected bug in [global] when dealing with
	variable names matching :*. [Bug 480176]

2001-11-08  Mo DeJong  <[email protected]>

	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  <[email protected]>

	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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIO.c (ReadChars): Fixed [Bug 478856] reported by Stuart
	Cassoff <[email protected]>. 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 <[email protected]>

	* 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  <[email protected]>

	* library/init.tcl: made filesystem fallback proc ::tcl::CopyDirectory
	more robust to vagaries of non-native filesystems.

2001-11-02  Vince Darley  <[email protected]>

	* doc/file.n:
	* generic/tclIOUtil.c: updated documentation and comments to clarify
	behaviour of 'file copy' wrt soft links.

2001-10-29  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/ObjectType.3: Minor documentation fix, reported by David N.
	Welton <[email protected]> directly to me.

2001-10-22  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIOUtil.c: fix to bug in Tcl_FSChdir shown up by recent
	tclkit builds.

2001-10-17  Jeff Hobbs  <[email protected]>

	* unix/tclUnixPipe.c (PipeInputProc, PipeOutputProc): do immediate
	retry when error is returned with errno == EINTR. [Bug 415131] (leger)

2001-10-16  Jeff Hobbs  <[email protected]>

	* unix/tclLoadAout.c (TclGuessPackageName): removed unused vars and
	fixed warnings. [Bug 446622] (lim)

2001-10-15  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclFCmd.c: fix to memory leak in TclFileDeleteCmd on
	certain error conditions.
	* doc/FileSystem.3: fix to typo.

2001-10-12  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* tests/unixInit.test:	Corrected restore of ::env(LANG).

2001-10-09  Jeff Hobbs	<[email protected]>

	* 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  <[email protected]>

	* generic/tclLiteral.c: (TclReleaseLiteral) reverted previous patch
	for [Bug 467523] - cure is worse than the illness.

2001-10-05  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIOUtil.c:
	* doc/FileSystem.3: corrected and clarified documentation for
	'Tcl_FSListVolumes(Proc)'. No code changes.

2001-09-28  Miguel Sofer  <[email protected]>

	* doc/FindExec.3: added a comment not to change the working directory
	before calling Tcl_GetNameOfExecutable. [Bug 219215]

2001-09-28  Kevin Kenny   <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>.

	* 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" <[email protected]>.

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c: removed comments referring to unused flag
	TCL_PARSE_PART1.

2001-09-24  Don Porter  <[email protected]>

	* 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  <[email protected]>

	The change below fixes [Bug 464380]. The bug was reported by Ronnie
	Brunner <[email protected]>. 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: insured that execution stack errors are also
	detected at abnormal returns.

2001-09-19  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIOCmd.c (Tcl_PutsObjCmd): Rewritten to have saner and
	faster argument handling. [Bug 123552], [Patch 402564] (fellows)

2001-09-18  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: corrected small bug in [Patch 456668] - the
	varFramePtr was not restored in one possible exit.

2001-09-17  Miguel Sofer  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>. Thanks to
	Christopher Nelson <[email protected]> for doing editorial work.

2001-09-13  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* generic/tcl.decls: reserved stub #481 for the implementation of
	[TIP 56]

2001-09-11  Andreas Kupries <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tcl.h:
	* generic/tclPlatDecls.h: Reminder from David Cuthbert
	<[email protected]> that I hadn't finished the Borland compatibility
	stuff. [Patch 436116]

2001-09-09  Mo DeJong  <[email protected]>

	* 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 <[email protected]>

	* win/mkd.bat:
	* win/rmd.bat: made these text files, text files again. [Patch 451333]

2001-09-08  Mo DeJong  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* tests/winFCmd.test: made notWin2000 constraint false if not running
	on Windows at all.

2001-09-04  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclProc.c:
	* tests/proc.test: made [proc] check that formal args have simple
	names. [Bug 458548]

2001-09-04 Vince Darley <[email protected]>

	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  <[email protected]>

	* generic/tclCompile.c: fixed incorrect operands for INST_LIST [Bug
	458241] (David Cuthbert, [email protected])

2001-09-03  Jeff Hobbs  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): fixed missing comma in
	debug macro.

2001-09-03  Donal K. Fellows  <[email protected]>

	* doc/ExprLongObj.3: Fixed error in documentation of argument type to
	Tcl_ExprObj [Bug 457435]

2001-09-02  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIndexObj.c: fixed some casting problems that upset Crays.
	[Bug 419528] (andreasen)

2001-08-30  Don Porter  <[email protected]>

	* generic/tcl.h: Silence warning from Sun compiler. [Bug 454374]

2001-08-30  Miguel Sofer  <[email protected]>

	* 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 <[email protected]>

	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 <[email protected]>

	* 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
	<[email protected]>

2001-08-28  Jeff Hobbs  <[email protected]>

	* generic/tclCompCmds.c (TclPushVarName): noted 'static' defn.
	[Bug 453872]

2001-08-26  Don Porter <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>.

2001-08-23  Jeff Hobbs  <[email protected]>

	* 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 <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* tests/ioUtil.test (ioUtil-3.*): Corrected errors in tests revealed
	by fix of overagressive compiler. [Bug 451200]

2001-08-21  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/trace.test: Corrected test numbers. [Bug 449794]

2001-08-12  Mo DeJong  <[email protected]>

	* 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 <[email protected]>

	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  <[email protected]>

	* generic/tclVar.c:
	* tests/trace.test: Insure that [array] traces work correctly for
	undefined variables. [Bug 449094]

2001-08-09  Mo DeJong  <[email protected]>

	* unix/Makefile.in: Delete the unused getcwd.o target. [Bug 440942]

2001-08-08  Don Porter <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* generic/tclIOUtil.c (Tcl_FSMatchInDirectory): corrected
	uninitialized value.

2001-08-02  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* doc/pkgMkindex.n:
	* library/package.tcl:  Corrected documentation and usage message of
	[pkg_mkIndex].

2001-07-18  Mo DeJong  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinPort.h: Add Cygwin specific defines for environ and
	timezone variables.

2001-07-17  Andreas Kupries <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* README:
	* mac/README:
	* unix/README:
	* win/README:
	* win/README.binary: updated READMEs with purls

2001-07-03  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclNamesp.c: Correction to faulty patch from [Bug 231259]

2001-06-28  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/event.test (event-11.5): Removed hard-coded port number which
	could fail on some systems. [Bug 436727]

2001-06-26  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tcl.m4 (SC_CONFIG_CFLAGS): Link to the imm32 library when
	building with mingw gcc.

2001-06-25  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* win/configure: Regen.
	* win/configure.in: Add resource compiler fix from 8.3.3 to fix
	compiling with mingw.

2001-06-22  Mo DeJong  <[email protected]>

	* win/configure: Regen.
	* win/tcl.m4: Fix silly typo in last checkin.

2001-06-22  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclUtil.c (Tcl_DStringAppendElement): patch to save an
	extra strlen call. [Bug 428572]

2001-05-30  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* library/init.tcl (unknown): removed errant " in error message

2001-05-27  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

2001-05-23  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* unix/tcl.m4 (SC_PATH_TCLCONFIG): Fix comments, and typo in cached
	variable name.

2001-05-23  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: removed Tcl_DuplicateObj in INST_DUP

2001-05-21  Jeff Hobbs  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/console.n: Deleted. Put it in the wrong source tree! D'oh!

2001-05-15  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* tests/lindex.test: added test for nested braces [Patch 423617]

2001-05-15  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: insure different rand() seeds in different
	threads. [Bug 416643]

2001-05-03  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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    <[email protected]>

	* 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    <[email protected]>

	* 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    <[email protected]>

	* unix/tclUnixTime.c: Fixed silly typo in calls to 'gmtime' and
	'localtime' that broke the Linux build.

2001-04-09  Kevin B. Kenny    <[email protected]>

	* 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    <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/Macintosh.3: Removed duplicates from .SH line. [Bug 413983]

2001-04-05  Donal K. Fellows  <[email protected]>

	* generic/tclCmdMZ.c (Tcl_StringObjCmd): Fixed so will compile
	with K&R compilers. [Patch 413844, Bug 413847]

2001-04-04  Don Porter  <[email protected]>

	* generic/tclMain.c:  Patch from Kevin Kenny to restore support of
	pre-ANSI compilers. [Bug 413846, Patch 413842]

2001-04-04  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinInt.h (tclWinTCharEncoding): Removed as now a static
	variable in win/tclWin32Dll.c instead.

2001-03-23  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/string.test: Fixed some test numberings and added a test.
	[Patch 403229]

2001-03-06  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* no changes; fixing up the missing comment in the previous one.
	Sorry.

2001-02-23  msofer  <[email protected]>

	* /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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/makefile.vc (install-libraries):  Corrected misdirected install
	directory for the msgcat 1.2 package.

2001-01-30  Don Porter  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/makefile.vc: some uses of xcopy swapped to the @$(CPY) macro.
	Reported by Joe Mistachkin <[email protected]>.

2002-12-17  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/README: Update msys build env URL. This release #4 build both
	tcl and tk without problems.

2002-11-22  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/Tcl.n: Corrected indentation of the new language. Oops.

2002-11-10  Kevin Kenny <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* library/word.tcl: Changed $tcl_platform to $::tcl_platform to avoid
	possible scope trouble.

2002-10-29  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* unix/tclLoadDyld.c (TclpFindSymbol): pass all dyld error messages
	upstream [Bug 627546].

2002-10-28  Andreas Kupries  <[email protected]>

	* library/dde/pkgIndex.tcl:
	* library/reg/pkgIndex.tcl: Changed the hardwired debug suffix (d) to
	the correct suffix (g).

2002-10-28  Don Porter  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/configure:                 add workaround for cygwin windres
	* win/tcl.m4 (SC_CONFIG_CFLAGS): problem. [Patch 624010] (howell)

2002-10-15  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclEnv.c (Tcl_PutEnv): correct possible mem leak. [Patch
	623269] (brouwers)

2002-10-11  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/binary.n: More clarification of [binary scan]'s behaviour.

2002-10-09  Daniel Steffen  <[email protected]>

	* generic/tclIntDecls.h: fixed botched regen.

2002-10-09  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/tcltest.n: fixed typo [Bug 618018]. Thanks to "JJM".

2002-10-03  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/socket.n: Mentioned that ports may be specified as serivce names
	as well as integers. [Bug 616843]

2002-09-30  Jeff Hobbs  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/README: Add note about building extensions with the same
	compiler Tcl was built with. [Tk Bug 592096]

2002-09-10  Daniel Steffen  <[email protected]>

	* macosx/Tcl.pbproj/project.pbxproj: disabled building html
	documentation during embedded build.

2002-09-10  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	*** 8.4.0 TAGGED FOR RELEASE ***

2002-09-06  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* tests/tcltest.test: Added nonRoot flag to tests 8.3, 8.4, and 8.12.

2002-09-05  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInterp.c (AliasCreate): a Tcl_Obj was leaked on error
	return from TclPreventAliasLoop.

2002-09-03  Daniel Steffen  <[email protected]>

	* macosx/Tcl.pbproj/project.pbxproj: Bumped version number to 8.4.0
	and updated copyright info.

2002-09-03  Miguel Sofer  <[email protected]>

	* generic/tclVar.c (Tcl_UpVar2): a Tcl_Obj was being leaked on error
	return from TclGetFrame.

2002-09-03  Don Porter  <[email protected]>

	* changes:  Updated changes for 8.4.0 release.

2002-09-02  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 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  <[email protected]>

	* win/tclWinThrd.c (TclpFinalizeThreadData, TclWinFreeAllocCache):
	Applied patch for [Bug 599428], provided by Miguel Sofer
	<[email protected]>.

2002-08-28  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclThreadAlloc.c: small optimisation, reducing the new
	allocator's overhead.

2002-08-23  Miguel Sofer  <[email protected]>

	* generic/tclObj.c (USE_THREAD_ALLOC): fixed leak [Bug 597936]. Thanks
	to Zoran Vasiljevic.

2002-08-23  Miguel Sofer  <[email protected]>

	* generic/tclThreadAlloc.c (USE_THREAD_ALLOC): moving objects between
	caches as a block, instead of one-by-one.

2002-08-22  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixTest.c (TestfilehandlerCmd): Changed readable/writable
	to the more common readable|writable. Fixes [Bug 596034] reported by
	Larry Virden <[email protected]>.

2002-08-16  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdMZ.c: fixing UMR in delete traces, [Bug 589863].

2002-08-08  David Gravereaux <[email protected]>

	* tools/man2help.tcl: Fixed $argv handling bug where if -bitmap wasn't
	specified $argc was off by one.

2002-08-08  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* tests/README: Noted removal of defs.tcl.

2002-08-08  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile.h:
	* generic/tclObj.c: making tclCmdNameType static ([Bug 584567], Don
	Porter).

2002-08-07  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: bugfix (reading freed memory). Testsuite
	passed on linux/i386, compile-13.1 hung on linux/alpha.

2002-08-01  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c: added a reference count for the complete
	execution stack, instead of Tcl_Preserve/Tcl_Release.

2002-08-01  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinPort.h: The windows headers don't provide socklen_t, so we
	have to do it.

2002-07-31  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInterp.c: signed/unsigned comparison warning fixed
	(Vince Darley).

2002-07-31  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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
	[email protected] for tracking this down.

2002-07-28  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c (TclObjLookupVar): leak fix and improved comments.

2002-07-26  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclProc.c: fix for [Tk Bug 219218] "error handling with
	bgerror in Tk"

2002-07-24  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c: restoring full TCL_COMPILE_DEBUG
	functionality.

2002-07-24  Don Porter  <[email protected]>

	* tests/unixInit.test: relaxed unixInit-3.1 to accept iso8859-15 as a
	valid C encoding. [Bug 575336]

2002-07-24  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in: Combine ranlib tests and avoid printing unless
	ranlib is actually run.

2002-07-23  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tclIOUtil.c: Silence compiler warning. [Bug 584408].

2002-07-19  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in: fix to build on MacOS X [Bug 529801], bug report
	and fix from jcw.

2002-07-19  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (CallCommandTraces): delete traces now receive
	the FQ old name of the command. [Bug 582532] (Don Porter)

2002-07-18  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c (DupParsedVarName): nasty bug fixed, reported by
	Vince Darley.

2002-07-17  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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    <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): Minor fixes to make this
	file compile with SunPro CC...

2002-07-17  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/configure: Regen.
	* unix/configure.in: Remove useless subst of TCL_BIN_DIR.

2002-07-15  Miguel Sofer  <[email protected]>

	* generic/tclVar.c: inaccurate comment fixed

2002-07-15  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/unixInit.test:	Improved constraints to protect /tmp. [Bug
	581403]

2002-07-15  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* changes: added recent changes

2002-07-05  Reinhard Max  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 8.4b1 TAGGED FOR RELEASE ***

2002-07-04  Donal K. Fellows  <[email protected]>

	* tests/cmdMZ.test (cmdMZ-1.4):
	* tests/cmdAH.test: More fixing of writable-current-dir assumption.
	[Bug 575824]

2002-07-04  Miguel Sofer  <[email protected]>

	* tests/basic.test: Same issue as below; fixed [Bug 575817]

2002-07-04  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/tcltest.n: Markup fixes, spellcheck.

2002-07-02  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* tests/fCmd.test:
	* generic/tclCmdAH.c: clearer error msgs for 'file link', as per the
	man page.

2002-07-01  Joe English  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/concat.n: Documented the *real* behaviour of [concat]!

2002-06-30  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixTime.c: Make [clock format] respect locale settings.
	* tests/clock.test:   [Bug 565880]. ***POTENTIAL INCOMPATIBILITY***

2002-06-26  Miguel Sofer  <[email protected]>

	* doc/CrtInterp.3:
	* doc/StringObj.3: clarifications by Don Porter, [Bug 493995] and [Bug
	500930].

2002-06-24  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompExpr.c:
	* generic/tclParseExpr.c: LogSyntaxError() should reset the
	interpreter result [Bug 550142 "Tcl_ExprObj -> abort"]

2002-06-21  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TclCompEvalObj): clarified and simplified the
	logic for compilation/recompilation.

2002-06-19  Joe English  <[email protected]>

	* doc/file.n: Fixed indentation. No substantive changes.

2002-06-19  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TEBC): removing unused "for(;;)" loop;
	improved comments; re-indentation.

2002-06-18  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TEBC, INST_DONE): small bug in the panic code
	for tcl-stack corruption.

2002-06-17  David Gravereaux <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinPipe.c (BuildCommandLine): Fixed [Bug 554068] ([exec] on
	windows did not treat { in filenames well.). Bug reported by Vince
	Darley <[email protected]>, patch provided by Vince
	too.

2002-06-17  Joe English  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile.c (TclCompileTokens): a better algorithm for the
	previous bug fix.

2002-06-16  Miguel Sofer  <[email protected]>

	* generic/tclCompile.c (TclCompileTokens):
	* tests/compile.test: [Bug 569438] in the processing of dollar
	variables; report by Georgios Petasis.

2002-06-16  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* win/rules.vc: The test for compiler optimizations was in error.
	Thanks goes to Roy Terry <[email protected]> for his assistance
	with this.

2002-06-14  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): consolidated code for the
	conditional branch instructions.

2002-06-13  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): fixed the previous patch;
	wouldn't compile with TCL_COMPILE_DEBUG set.

2002-06-13  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tclBasic.c (Tcl_DeleteTrace): fixed [Bug 568123] (thanks to Hemang
	Lavana)

2002-06-12  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: optimised algorithm for exception range
	lookup; part of [Patch 453709].

2002-06-10  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/README: Update msys+mingw URL.

2002-06-03  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* doc/namespace.n: added description of [namepace forget] behaviour
	for unqualified patterns. [Bug 559268]

2002-06-03  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c: reverting an accidental modification in the
	last commit.

2002-06-03  Miguel Sofer  <[email protected]>

	* doc/Tcl.n: clarify the empty variable name issue ([Bug 549285]
	reported by Tom Krehbiel, patch by Don Porter).

2002-05-31  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	=== 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  <[email protected]>

	* tests/winPipe.test: Applied patch for [Bug 549617]. Patch and bug
	report by Kevin Kenny <[email protected]>.

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/CrtObjCmd.3: Added Tcl_GetCommandFromObj, Tcl_GetCommandFullName
	[Bugs 547987, 414921]

2002-05-14  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* doc/file.n:
	* tools/man2tcl.c:
	* tools/man2help2.tcl:  Thanks to Peter Spjuth
	<[email protected]>, 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	-- Changes from Peter Spjuth <[email protected]>
	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/exec.n:
	* doc/tclvars.n: doc updates [Patch 509426] (gravereaux)

2002-04-24  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* doc/TraceCmd.3: New file that documents Tcl_CommandTraceInfo,
	Tcl_TraceCommand and Tcl_UntraceCommand [Bug 414927]

2002-04-22  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/lindex.test (lindex-3.7):
	* generic/tclUtil.c (TclGetIntForIndex): Stopped indexes from hitting
	wide ints. [Bug 526717]

2002-04-18  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/tcltest/tcltest.tcl: added getMatchingFiles back (alias to
	GetMatchingFiles), which was a public function in tcltest 1.0.

2002-04-01  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c: Refactored CallTraces to collect repeated handling
	of its returned value into CallTraces itself.

2002-03-28  David Gravereaux <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (Tcl_EvalEx): passing the correct commandSize to
	TclEvalObjvInternal. [Bug 219362], fix by David Knoll.

2002-03-28  Miguel Sofer  <[email protected]>

	* generic/tclBasic.c (Tcl_EvalEx):
	* tests/basic.test: avoid exceptional returns at level 0. [Bug 219181]

2002-03-27  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (Tcl_EvalObjv): replaced obscure, incorrect code
	as described in [Bug 533907] (Don Porter).

2002-03-24  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/basic.test (basic-46.1): adding test for [Bug 533758], fixed
	earlier today.

2002-03-22  Jeff Hobbs  <[email protected]>

	* win/tclWinInt.h: moved undef of TCL_STORAGE_CLASS. [Bug 478579]

2002-03-22  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* doc/expr.n: Improved documentation for ceil and floor. [Bug 530535]

2002-03-20  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/tcltest/tcltest.tcl:
	* library/tcltest/pkgIndex.tcl: Bumped tcltest package to 2.0.2.

2002-03-11  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinFCmd.c (DoCopyFile): correctly set retval to TCL_OK.

2002-03-07  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: Replaced a few direct stack accesses with the
	POP_OBJECT() macro [Bug 507181] (Don Porter).

2002-02-27  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/socket.test (2.7): Accepted and applied patch for [Bug 523470]
	provided by Don Porter <[email protected]> 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* mac/tclMacSock.c (TcpGetOptionProc): Changed to recognize the option
	"-error". Essentially ignores the option, always returning an empty
	string.

2002-02-25  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* compat/strtoul.c, compat/strtol.c, compat/strtod.c: Added UCHAR,
	CONST and #includes to clean up GCC output.

2002-02-23  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	--- 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* generic/tcl.h: Better guessing of LP64/ILP32 architecture, but now
	sensitive to presence of (suitable) <limits.h>

2002-02-20  Don Porter <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* changes: First draft of updated changes for 8.4a4 release.

2002-02-15  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	+----------------------+
	| 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  <[email protected]>

	* generic/tclIOCmd.c (Tcl_GetsObjCmd): Trivial fix for [Bug 517503], a
	memory leak reported by Miguel Sofer <[email protected]>. The leak
	happens if an error occurs for "set var [gets $chan]" and leak one
	empty object.

2002-02-12  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixChan.c (FileOutputProc): Fixed [bug 465765] reported by
	Dale Talcott <[email protected]>. 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  <[email protected]>

	* generic/tclCmdMZ.c (Tcl_RegexpObjCmd): handle quirky about case
	earlier to avoid shimmering problem.

2002-02-01  Andreas Kupries  <[email protected]>

	* 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 <[email protected]>

	* generic/tclTest.c: fix to picky windows compiler problem with the
	'MainLoop' function declaration.

2002-01-31  Andreas Kupries  <[email protected]>

	* win/tclWinFCmd.c: TIP 27: Applied patch fixing CONST warnings on
	behalf of Don Porter <[email protected]>.

2002-01-30  Don Porter <[email protected]>

	* 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 <[email protected]>

	* doc/FileSystem.3: added documentation for 3 public functions which
	had been overlooked. [Bug 507701]
	* unix/mkLinks: make mklinks

2002-01-29  Jeff Hobbs  <[email protected]>

	* tests/regexpComp.test:
	* generic/tclCompCmds.c (TclCompileRegexpCmd): enhanced to support
	-nocase and -- options.

2002-01-28  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* doc/package.n: Documented global namespace context for script
	evaluation by [package require].

2002-01-27  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	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 <[email protected]>

	* 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 <[email protected]>

	* generic/tclIOUtil.c (SetFsPathFromAny):  Corrected tilde-substitution
	of pathnames where > 1 separator follows the ~. [Bug 504950]

2002-01-24  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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
	<[email protected]>.

2002-01-23  Don Porter <[email protected]>

	* 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 <[email protected]>

	* generic/tclLoadNone.c: TclpLoadFile() didn't match proto of typedef
	Tcl_FSLoadFileProc. OK'd by vincentdarley. [Patch 502488]

2002-01-21  Andreas Kupries  <[email protected]>

	* generic/tclIO.c (WriteChars): Fix for [Bug 506297], reported by
	Martin Forssen <[email protected]>. 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIOCmd.c (Tcl_GetsObjCmd): Fixed [Bug 504642] as reported
	by Brian Griffin <[email protected]>, 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinSerial.c (SerialSetOptionProc): Applied patch for [Bug
	500348] supplied by Rolf Schroedter <[email protected]>. 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>,
	Kevin Kenny <[email protected]>

	* 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 <[email protected]>,
	Kevin Kenny <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* mac/tclMacTime.c (TclpGetTZName): fix for daylight savings TZName bug

2002-01-03  Don Porter <[email protected]>

	* doc/FileSystem.3:
	* generic/tclIOUtil.c: Updated some old uses of "fileName" to
	new VFS terminology, "pathPtr".

2002-01-03  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* generic/tclBinary.c (DeleteScanNumberCache): fixed crashing bug when
	numeric scan-value cache contains NULL value.

2003-12-17  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* generic/tclPathObj.c:
	* tests/fileSystem.test: fix and tests for [Bug 860402] in new file
	normalization code.

2003-12-17  Zoran Vasiljevic  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclThreadAlloc.c (binfo): Made variable file-local.

2003-12-15  David Gravereaux <[email protected]>

	* 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 <[email protected]> [Patch 758097].

2003-12-14  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* unix/configure:
	* unix/tcl.m4: updated OpenBSD build configuration based on
	[Patch #775246] (cassoff)

2003-12-09  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* doc/lset.n: fix typo [Bug 852224]

2003-11-24  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* tests/winFCmd.test (winFCmd-16.10,11): Merged new tests from
	core-8-4-branch.

2003-11-20  Miguel Sofer <[email protected]>

	* generic/tclVar.c: fix flag bit collision between LOOKUP_FOR_UPVAR
	and TCL_PARSE_PART1 (deprecated) [Bug 835020]

2003-11-19  Don Porter	<[email protected]>

	* tests/compile.test (compile-16.22.0):	Improved test for the recent
	fix for Bug 845412.

2003-11-19  Donal K. Fellows  <[email protected]>

	* 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 <[email protected]>

	* contrib/djgpp/Makefile:		Changes from Victor Wagner
	* contrib/djgpp/langinfo.c (new):	<[email protected]> for better
	* contrib/djgpp/langinfo.h (new):	DJGPP support.
	* unix/tclUnixInit.c:			.
	* unix/tclUnixChan.c:			.
	* unix/tclUnixFCmd.c:			.

2003-11-17  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* contrib/djgpp/Makefile:  Suggested changes from [email protected]
	(Victor Wagner)

	* unix/tclUnixPort.h:  added socklen_t typedef for DJGPP

2003-11-10  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdAH.c:
	* tests/fCmd.test: fix to misleading error message in 'file link'.
	[Bug 836208]

2003-11-07  Vince Darley  <[email protected]>

	* generic/tclIOUtil.c: fix to compiler warning/error with some
	compilers. [Bug 835918]

2003-11-07  Daniel Steffen  <[email protected]>

	* macosx/Makefile: optimized builds define NDEBUG to turn off
	ThreadAlloc range checking.

2003-11-05  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* macosx/Makefile: added 'test' target.

2003-11-03  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tclExecute.c (NEXT_INST macros): replaced macro variable
	"result" by "resultHandling" to avoid confusion.

2003-10-23  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinPipe.c (BuildCommandLine): Applied the patch coming with
	[Bug 805605] to the code, fixing the incorrect use of ispace noted by
	Ronald Dauster <[email protected]>.

2003-10-20  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* win/tclAppInit.c (sigHandler): Punt gracefully if exitToken has
	already been destroyed.

2003-10-14  Vince Darley  <[email protected]>

	* generic/tclCmdMZ.c:
	* tests/regexp.test: fix to [Bug 823524] in regsub; added three new
	tests.

2003-10-14  Don Porter	<[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixTest.c (TestalarmCmd): don't bother checking return
	value of alarm. [Bug #664755] (english)

2003-10-09  Pat Thoyts  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* macosx/Makefile: fixed redo prebinding bug when DESTDIR="".
	* mac/tclMacResource.c: fixed possible NULL dereference (bdesgraupes).

2003-09-29  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* trace.test: removed 'knownBug' from a test which doesn't illustrate
	a bug, just a bad test.

2003-09-23  Miguel Sofer <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/catch.n:	Updated [catch] docs to cover new TIP 90 features.

2003-08-29  Don Porter  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinSerial.c (SerialErrorStr): Fixed a syntax error created in
	the previous code cleanup.

2003-08-19  Donal K. Fellows  <[email protected]>

	* win/tclWinSerial.c: Adjusted commenting and spacing usage to follow
	the principles of the Style Guide better.

2003-08-18  Mo DeJong  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	TIP #136 IMPLEMENTATION from Simon Geard <[email protected]>
	* 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  <[email protected]>

	* win/tclWinInit.c: recognize amd64 and ia32_on_win64 cpus.

2003-08-06  Don Porter  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* doc/FileSystem.3:
	* doc/Translate.3: better documentation of Tcl_TranslateFileName and
	related functions. [Bug 775220]

2003-07-24  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* test/cmdAH.test: ensure certain tests run in local filesystem. [Bug
	748960]

2003-07-18  Daniel Steffen  <[email protected]>

	* macosx/Makefile: added option to allow installing manpages in
	addition to default html help.

2003-07-18  Donal K. Fellows  <[email protected]>

	* doc/Utf.3: Tightened up documentation of Tcl_UtfNext and Tcl_UtfPrev
	to better match the behaviour. [Bug 769895]

2003-07-18  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/dltest/pkga.c (Pkga_EqObjCmd): Fix typo that was causing a
	crash in load.test.

2003-07-15  Donal K. Fellows  <[email protected]>

	* doc/array.n: Make sure docs are synched with the 8.4 release.

2003-07-15  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* win/rules.vc: Added a missing $(OPTDEFINES) which broke the build if
	STATS=memdbg was specified.

2003-07-15  Donal K. Fellows  <[email protected]>

	* generic/tclCmdIL.c (SortCompare): Cleared up confusing error
	message. [Bug 771539]

2003-07-11  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/winFCmd.test: fix for five tests under win98 [Bug 767679]

2003-07-07  Jeff Hobbs  <[email protected]>

	* doc/array.n: add examples from Welton

2003-06-23  Vince Darley  <[email protected]>

	* doc/file.n: clarification of 'file tail' behaviour [Bug 737977]

2003-07-04  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclTrace.c: fix to Window debug build compilation error.

2003-06-27  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* tests/init.test:  Added tests init-4.6.* to illustrate [Bug 760872]

2003-06-25  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclHash.c (Tcl_HashStats): Prevented occurrence of
	division-by-zero problems.  [Bug 759749]

2003-06-24  Mo DeJong  <[email protected]>

	* unix/tclUnixPort.h: #undef inet_ntoa before #define to avoid
	compiler warning under freebsd. [Bug 745844]

2003-06-23  Pat Thoyts  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tclNamesp.c (Tcl_Export): removed erroneous comments. [Bug
	756744]

2003-06-17  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in:	Removed one excess source file tclDToA.c

2003-05-16  Daniel Steffen  <[email protected]>

	* macosx/Tcl.pbproj/project.pbxproj: updated copyright year.

2003-05-15  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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 <[email protected]>

	* 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  <[email protected]>

	* generic/tclIOUtil.c: ensure cd is thread-safe.
	[Bug 710642] (vasiljevic)

2003-05-13  Donal K. Fellows  <[email protected]>

	* generic/tclEvent.c (Tcl_Finalize): Removed unused variable to reduce
	compiler warnings. [Bug 664745]

2003-05-13  Joe Mistachkin  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (Tcl_HideCommand): Fixed error message for
	grammar and spelling.

2003-04-28  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/socket.n: Added a paragraph to remind people to specify their
	encodings when using sockets. [Bug 630621]

2003-04-16  Donal K. Fellows  <[email protected]>

	* doc/CrtMathFnc.3: Functions also have to deal with wide ints, but
	this was not documented. [Bug 709720]

2003-04-16  Vince Darley  <[email protected]>

	* generic/tclPathObj.c: removed undesired 'static' for function which
	is now shared (previously it was duplicated).

2003-04-15  Joe English  <[email protected]>

	* doc/namespace.n: added example section "SCOPED SCRIPTS", supplied by
	Kevin Kenny. [Bug 219183]

2003-04-15  Kevin Kenny  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIOUtil.c: finished check-in from yesterday, removing
	duplicate function definition.

2003-04-14  Don Porter  <[email protected]>

	* generic/tclClock.c:	Corrected compiler warnings.
	* generic/tclTest.c:

2003-04-14  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinFile.c: added conditionals to restore compilation on
	VC++6, which was broken by recent changes.

2003-04-14  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/Makefile.in (GENERIC_OBJS): add missing tclPathObj.c

2003-04-12  Kevin Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/binary.n: Fixed typo in [binary format w] desc. [Bug 718543]

2003-04-08  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* library/dde/pkgIndex.tcl: bumped version to 1.2.2 in tclWinDde.c,
	now adding here too.

2003-03-22  Kevin Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tclCompile.c:
	* tests/compile.test: bad command count on TCL_OUT_LINE_COMPILE.
	[Bug 705406] (Don Porter)

2003-03-19  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/format.test: Renumber tests, a bunch of tests all had the same
	id.

2003-03-17  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tcl.m4 (SC_WITH_TCL): Port version number fix that was made in
	tk instead of tcl sources.

2003-03-13  Mo DeJong  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* win/makefile.vc: Added two missing uses of $(DBGX) so that
	tclpip8x.dll loads without panicking on Win9x.

2003-03-09  Kevin Kenny  <[email protected]>

	* generic/tclTest.c (TestChannelCmd): Removed an unused local variable
	that caused compilation problems on some platforms.

2003-03-08  Don Porter  <[email protected]>

	* doc/tcltest.n:  Added missing "-body" to example. Thanks to Helmut
	Giese. [Bug 700011]

2003-03-07  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/io.test: Doh! Undo accidental commenting out of a couple of
	tests.

2003-03-06  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompCmds.c (TclCompileSwitchCmd):
	Replaced a non-portable 'bzero' with a portable 'memset'. [Bug 698442]

2003-03-06  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/rules.vc: updated default tcl version to 8.5.

2003-03-05  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	*** 8.4.2 TAGGED FOR RELEASE ***

2003-03-03  Daniel Steffen  <[email protected]>

	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  <[email protected]>

	* win/Makefile.vc: corrected bug introduced by 'g' for debug builds.

2003-03-03  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/file.n: subcommand is 'file volumes' not 'file volume'

2003-02-27  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* generic/tclCmdMZ.c (TraceCommandProc): Fix mem leak when deleting a
	command that had trace on it. [Bug 693564] (sofer)

2003-02-25  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* tests/pid.test: See below [Bug 678412].
	* tests/io.test: Made more robust against spaces in paths [Bug 678400]

2003-02-25  Miguel Sofer <[email protected]>

	* tests/execute.test: cleaning up testobj's at the end, to avoid
	  leak warning by valgrind.

2003-02-22  Zoran Vasiljevic  <[email protected]>

	* generic/tclEvent.c (Tcl_FinalizeThread): Fix [Bug 571002]

2003-02-21  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* mac/tclMacChan.c (TclpCutFileChannel, TclpSpliceFileChannel):
	Implemented missing cut and splice procs for file channels.

2003-02-21  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/regsub.n: Typo fix [Bug 688943]

2003-02-19  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclTest.c: cleanup of new 'simplefs' test code, and better
	documentation.

2003-02-17  Miguel Sofer <[email protected]>

	* generic/tclBasic.c (TclRenameCommand): fixing error in previous
	commit.

2003-02-17  Jeff Hobbs  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/notify.test: Removed Windows line terminators. [Bug 687913].

2003-02-15  Miguel Sofer <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tclParse.c (CommandComplete):
	* tests/parse.test: fix for [Bug 684744], by Don Porter.

2003-02-11  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/append.n: Return value was not documented. [Bug 683188]

2003-02-10  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* library/safe.tcl: code cleanup of eval and string comp use.

2003-02-07  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/main.test: Constrain tests that do not work on Windows. [Bug
	674387]

2003-01-28  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/README: Update msys+mingw URL to release 6. This version bundles
	gcc 3.

2003-01-26  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/namespace.n (namespace inscope): Clarified documentation
	[Patch 670110]

2003-01-21  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCkalloc.c: change %ud to %u as appropriate.

2003-01-17  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclClock.c (FormatClock): corrected typo that incorrectly
	conditionally defined savedTZEnv and savedTimeZone.

2003-01-13  Mo DeJong  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompCmds.c (TclCompileReturnCmd):  Corrected off-by-one
	problem with recent commit. [Bug 633204]

2003-01-09  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TclExprFloatError):  Use the IS_NAN macro for
	greater clarity of code.

2003-01-07  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tclVar.c (TclArrayObjCmd - ARRAY_NAMES): leaking an object
	[Bug 1084111] - thanks to Rolf Ade.

2004-12-12  Miguel Sofer <[email protected]>

	* generic/tclObj.c (TclSetCmdNameObj): special handling for fully
	qualified command names (as in fix [Patch 456668]).

2004-12-11  Miguel Sofer <[email protected]>

	* generic/tclInt.h:
	* generic/tclNamesp.c: converting the static function
	GetNamespaceFromObj() to MODULE_SCOPE TclGetNamespaceFromObj().

2004-12-10  Donal K. Fellows  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.h: Move ensemble API decls here from tclNamesp.c

2004-12-09  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	*** 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	<[email protected]>

	* 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	<[email protected]>

	* tests/safe.test:	Trim auto_path to improve performance [1080039]

	* tests/msgcat.test:	makeFile/removeFile cleanup [1079117]

2004-12-04  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* changes: updated for 8.5a2 release

2004-12-02  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* doc/Thread.3:
	* doc/Notifier.3: Added changes from the core-8-4-branch

2004-11-25  Donal K. Fellows  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* doc/AddErrInfo.3:	Typo corrections (Thanks Daniel South).
	* doc/interp.n:

2004-11-19  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* unix/tclUnixChan.c (TtySetOptionProc): fixed crash configuring
	-ttycontrol on a channel. [Bug 1067708]

2004-11-16  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* doc/tclvars.n: Added section to documentation on global variables
	that are specific to tclsh and wish. [Patch 1065732]

2004-11-12  Jeff Hobbs	<[email protected]>

	* generic/tclEncoding.c (TableFromUtfProc): correct crash condition
	when TCL_UTF_MAX == 6. [Bug 1004065]

2004-11-12  Donal K. Fellows  <[email protected]>

	* doc/interp.n: Basic documentation of the TIP#221 API.

2004-11-12  Don Porter	<[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* tests/winFile.test: added contraint to winFile-4.0 to prevent it
	being run on NT4 [Bug 981829]

2004-11-05  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* changes:	Updates toward an 8.5a2 release.

2004-11-03  Kevin B. Kenny  <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): Improved version of the
	NaN fix from Miguel Sofer. [Bug 761471]

2004-11-02  Kevin Kenny	 <[email protected]>

	* 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  <[email protected]>

	* win/tclWinFile.c: Simplify TclpUtime to use Tcl_FSGetNativePath, and
	add comments.

2004-11-02  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* tests/format.test (format-19.1): Additional regression test for [Bug
	868489].

2004-10-27  Donal K. Fellows  <[email protected]>

	* doc/*.n: Many small general documentation fixes.

2004-10-26  David Gravereaux <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* generic/tclInt.h:
	* generic/tclVar.c: removed more direct references to the VAR flags,
	replaced with access macros.

2004-10-26  Donal K. Fellows  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]> for finding
	these bugs.

2004-10-22  Donal K. Fellows  <[email protected]>

	* generic/tclExecute.c (TclCompEvalObj, Tcl_ExprObj):
	* generic/tclProc.c (TclProcCompileProc): Always call object
	freeIntRepProc's in the same way.

2004-10-22  Miguel Sofer <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* generic/tclResult.c: removed unused variable [Bug 1048588]. Thanks
	to Daniel South.

2004-10-15  Don Porter	<[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	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	<[email protected]>

	* generic/tclTest.c (TestsetobjerrorcodeCmd):  Simplified.

2004-10-07  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* *.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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* tests/subst.test (12.1-2): added tests for [Bug 1036649]

2004-09-29  Don Porter	<[email protected]>

	* tests/basic.test (49.*): New tests for TCL_EVAL_GLOBAL.

2004-09-29  Donal K. Fellows  <[email protected]>

	* 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 <[email protected]>

	* generic/tclBasic.c (TclObjInvoke): fix for bogus gcc warning about
	uninitialised variable.

2004-09-27  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	 <[email protected]>

	* 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  <[email protected]>

	* doc/FileSystem.3: fix to small typo.

2004-09-26  Miguel Sofer <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* tests/error.test (error-6.2,3):	Added more tests to verify
	::errorCode setting by/after a [catch].

2004-09-19  Miguel Sofer <[email protected]>

	* generic/tclCmdAH.c: removed outdated comment [Bug 1029518].

2004-09-18  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tclExecute.c (INST_CONCAT1): fix for [Bug 1025834]; avoid
	unnecessary string copies.

2004-09-10  David Gravereaux <[email protected]>

	* tests/tcltest.test: tcltest-12.3-4 needed to have
	::tcltest::loadScript set to empty in their -setup

2004-09-10  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tcl.h: Micro formatting fixes.
	* generic/tclIOGT.c: Channel version fixed, must be 3, to have
	wideseekProc. Thanks to David Graveraux <[email protected]>.

2004-09-11  Don Porter	<[email protected]>

	* 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	 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* win/tclWinConsole.c: Calls to WriteFile and WriteConsoleA changed to
	WriteConsole for simplicity.

2004-09-09  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* win/makefile.vc: some quoting needed to be removed as it was
	breaking with VC7. [Bug 1023150]

2004-09-07  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixFCmd.c: Stop NULL interp arguments from triggering a
	crash when an error happens. [Bug 1020538]

2004-09-02  Donal K. Fellows  <[email protected]>

	* doc/lsearch.n: Clarified meaning of -dictionary. [Bug 759545]

2004-09-02  Vince Darley  <[email protected]>

	* win/makefile.vc: clock.tcl needs to be installed.

2004-09-01  Jeff Hobbs	<[email protected]>

	* 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  <[email protected]>

	* doc/regsub.n, doc/RegConfig.3, doc/Environment.3:
	* doc/CrtChannel.3, doc/safe.n: Use correct abbreviations.

2004-08-31  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in (install-libraries): portable sh fix.

2004-08-30  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* doc/string.n: Added clarifying note.

2004-08-23  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclScan.c (Tcl_ScanObjCmd, ValidateFormat): Ensure that the
	%ld conversion works correctly on 64-bit platforms. [Bug 1011860]

2004-08-19  Kevin Kenny	 <[email protected]>

	* 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  <[email protected]>

	* 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	 <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* tests/io.test: Make io-61.1 create file as binary to pass on Win32

2004-07-23  Miguel Sofer <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* win/tclwinThrd.c: redefined MASTER_LOCK to call TclpMasterLock.
	Fixes [Bug 987967]

2004-07-17  Vince Darley  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>.

	* tests/socket.test: Accepted two new testcases by Stuart Casoff
	<[email protected]> 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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
	<[email protected]>.

2004-07-15  Zoran Vasiljevic <[email protected]>

	* 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	 <[email protected]>

	* generic/tclLiteral.c (TclReleaseLiteral): Removed unused variable
	'codePtr' to silence a message from VC++.

2004-07-15  Miguel Sofer <[email protected]>

	* 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 <[email protected]>

	* generic/tclEvent.c (NewThreadProc): Backout of changes to fix the
	[Bug 770053]. See SF bugreport for more info.

2004-07-11  Miguel Sofer <[email protected]>

	* generic/tclBasic.c (Tcl_EvalEx): leak fix by dgp, release
	objv[objectsUsed] on error.

2004-07-11  Miguel Sofer <[email protected]>

	* generic/tclParse.c (Tcl_SubstObj): leak fix by dgp, release result
	on error.

2004-07-11  Donal K. Fellows  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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	 <[email protected]>

	* 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 <[email protected]>

	* 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	 <[email protected]>

	* win/tclWinInit.c (AppendEnvironment): Silenced a compilation warning
	about a type mismatch.

2004-07-07  Miguel Sofer <[email protected]>

	* 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	<[email protected]>

	* generic/tclCmdMZ.c (TclMergeReturnOptions):  Simplified logic and
	removed potential memory leak. [Bug 986257].

2004-07-07  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/fileSystem.test: Added test for [Bug 970529]

2004-07-01  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* tests/fileSystem.test: Minor correction to new fileSystem-9.X tests
	so that they clean up temporary directories correctly.

2004-06-30  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	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	<[email protected]>

	* win/tclWinInit.c:	Corrected reference counting flaw in recent
	changes. Thanks to Pat Thoyts. [Bug 981893].

2004-06-29  Vince Darley  <[email protected]>

	* win/tclWin32Dll.c: fix to compilation with VC++ 5.2

2004-06-29  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* tests/unixNotfy.test: Modified constraints so that testing with a
	threaded tclsh (not tcltest) will not hang.

2004-06-23  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tcl.m4: autoconf 2.5 fixes in Darwin section.
	* unix/configure: autoconf-2.57

2004-06-18  Donal K. Fellows  <[email protected]>

	* unix/tclUnixInit.c (localeTable): Added some more locale to encoding
	mapping info from Jim Huang <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	 <[email protected]>

	* 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	<[email protected]>

	* 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	 <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* generic/tclCompile.c:
	* generic/tclExecute.c: handle warning [Bug 969066]

2004-06-08  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* doc/lsearch.n: Added correct option to example. [Bug 968219]

2004-06-05  Kevin B. Kenny  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* doc/file.n: fix to documentation of 'file volumes' (Bug 962435)

2004-06-01  David Gravereaux <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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	 <[email protected]>

	* doc/global.n, doc/interp.n, doc/lrange.n: Fix minor markup errors.

2004-05-28  Donal K. Fellows  <[email protected]>

	* doc/*.n: Added examples to many (too many to list) more man pages.

2004-05-25  Miguel Sofer <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* docs/global.n: added details for qualified variable names [Bug
	959831]

2004-05-25  Miguel Sofer <[email protected]>

	* 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	 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclInterp.c (TclInitLimitSupport): Made limits work on
	platforms where sizeof(void*)!=sizeof(int). [Bug 959193]

2004-05-24 Miguel Sofer <[email protected]>

	* doc/set.n: accurate description of name resolution process,
	referring to namespace.n for details [Bug 959180]

2004-05-23  Miguel Sofer <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/append.n, doc/upvar.n: Added example.

2004-05-18  David Gravereaux <[email protected]>

	* win/makefile.vc: now generates a tclConfig.sh from Pat Thoyts [Patch
	909911]

2004-05-18  Donal K. Fellows  <[email protected]>

	* 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 <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): added comments to
	classify the variables according to their use in TEBC.

2004-05-17  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinFile.c:
	* tests/cmdAH.test: fix to (Bug 954263) where 'file executable' was
	case-sensitive.

2004-05-17  Donal K. Fellows  <[email protected]>

	* doc/OpenFileChnl.3: Documented type of 'offset' argument to Tcl_Seek
	was wrong. [Bug 953374]

2004-05-16  Miguel Sofer <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): remove one level of
	indirection for compiledLocals addressing.

2004-05-16  Miguel Sofer <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	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 <[email protected]>

	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  <[email protected]>

	* doc/split.n, doc/join.n: Updated examples and added more.

2004-05-11  Vince Darley  <[email protected]>

	* doc/glob.n: documented behaviour of symbolic links with 'glob -types
	d' (Bug 951489)

2004-05-11  Donal K. Fellows  <[email protected]>

	* doc/scan.n: Updated the examples to be clearer about their relevance
	to the scan command.

2004-05-10  Donal K. Fellows  <[email protected]>

	* doc/scan.n: Added examples.

2004-05-10  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* generic/tclFileName.c:
	* generic/tclIOUtil.c: remove some compiler warnings on MacOS X.

2004-05-07  Chengye Mao <[email protected]>

	* 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  <[email protected]>

	* doc/format.n: Added examples.

2004-05-07  Miguel Sofer <[email protected]>

	* doc/unset.n: added upvar.n to the "see also" list

2004-05-07  Reinhard Max  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* doc/break.n, doc/continue.n, doc/for.n, doc/while.n: More examples.

2004-05-05  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* doc/CrtObjCmd.3: Remove reference to Tcl_RenameCommand; there is no
	such API. [Bug 848440]

2004-05-05  David Gravereaux <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclEvent.c (TclSetLibraryPath): Suppress a warning.

2004-05-03  Andreas Kupries  <[email protected]>

	* Applied [Patch 868853], fixing a mem leak in TtySetOptionProc.
	Report and Patch provided by Stuart Cassoff <[email protected]>.

2004-05-03  Miguel Sofer <[email protected]>

	* generic/tclProc.c (TclCreateProc): comments corrected.

2004-05-03  Miguel Sofer <[email protected]>

	* generic/tclCompile.c (TclCompileScript): setting the compilation
	namespace outside of the loop.

2004-05-03  Miguel Sofer <[email protected]>

	* 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	 <[email protected]>

	* 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	<[email protected]>

	* library/init.tcl:	Corrected unique prefix matching of
	interactive command completion in [unknown]. [Bug 946952]

2004-05-02  Miguel Sofer <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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   <[email protected]>

	* 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  <[email protected]>

	* doc/puts.n: Added a few examples.

2004-04-29  Don Porter	<[email protected]>

	* tests/execute.test (execute-8.2):	Avoid crashes when there is
	limited system stack space (threads-enabled).

2004-04-28  Miguel Sofer <[email protected]>

	* 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  <[email protected]>

	* doc/lsearch.n: Fixed fault in documentation of -index option [943448]

2004-04-26  Don Porter	<[email protected]>

	* unix/tclUnixFCmd.c (TclpObjNormalizePath):  Corrected improper
	positioning of returned checkpoint. [Bug 941108]

2004-04-26  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* generic/tcl.h:	Removed obsolete declarations and #include's.
	* generic/tclInt.h:	[Bugs 926459, 926486]

2004-04-24  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* doc/read.n: Added example from David Welton. [Patch 938056]

2004-04-19  Kevin B. Kenny   <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/FileSystem.3: Corrected documentation of Tcl_FSUtime, and the
	corresponding filesystem driver Tcl_FSUtimeProc. [Bug 935838]

2004-04-16  Donal K. Fellows  <[email protected]>

	* doc/socket.n: Added example from [Patch 936245].
	* doc/gets.n: Added example based on [Patch 935911].

2004-04-15  Donal K. Fellows  <[email protected]>

	* generic/tclClock.c (Tcl_ClockObjCmd): Minor fault in a [clock
	clicks] error message.

2004-04-07  Jeff Hobbs	<[email protected]>

	* 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	<[email protected]>

	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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* generic/tclCompile.h: removed redundant #ifdef _TCLINT [Bug 928415],
	reported by tauvan.

2004-04-02  Don Porter	<[email protected]>

	* tests/tcltest.test: Corrected constraint typos: "nonRoot" ->
	"notRoot". Thanks to Steven Abner (tauvan). [Bug 928353]

2004-04-01  Don Porter	<[email protected]>

	* generic/tclInt.h:  Removed obsolete tclBlockTime* declarations. [Bug
	926454]

2004-04-01  Vince Darley  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclPathObj.c:	  Fix to filename bugs recently
	* tests/fileName.test:	  introduced [Bug 918320].

2004-03-29  Don Porter	<[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* doc/array.n: added documentation for trace-realted behaviour of
	'array get' [Bug 449893]

2004-03-26  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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   <[email protected]>

	* 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  <[email protected]>

	* generic/tclIntDecls.h: Made HEAD build on Solaris again by applying
	fix recommended by Don Porter.

2004-03-18  Reinhard Max  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* unix/configure, unix/tcl.m4: add -Wno-strict-aliasing for GCC to
	suppress useless type puning warnings.

2004-03-16  Donal K. Fellows  <[email protected]>

	* doc/file.n: *roff formatting fix. [Bug 917171]

2004-03-15  David Gravereaux <[email protected]>

	* 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  <[email protected]>

	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 <[email protected]>

	* 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  <[email protected]>

	* generic/tclFileName.c:  Fix to 'glob -path' near the root
	* tests/fileName.test:	  of the filesystem. [Bug 910525]

2004-03-08  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* unix/dltest/pkgua.c: Fix minor syntax problems. [Bug 909288]

2004-03-03  Jeff Hobbs	<[email protected]>

	*** 8.5a1 TAGGED FOR RELEASE ***

	* changes: updated for 8.5a1

2004-03-03  David Gravereaux <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* macosx/Makefile: fixed copyright year in Tcl.framework Info.plist

2004-02-25  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* generic/regc_locale.c (cclass): Buffer was having its size reset
	instead of being released => memleak. [Bug 902562]

2004-02-21  Donal K. Fellows  <[email protected]>

	* generic/tclLoad.c (Tcl_LoadObjCmd): Fixed memory leak due to an
	improper error exit route.

2004-02-20  David Gravereaux <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclCompCmds.c (TclCompileSwitchCmd): Bozo mistake in memory
	releasing order when in an error case. [Bug 898910]

2004-02-16  Jeff Hobbs	<[email protected]>

	* generic/tclTrace.c (TclTraceExecutionObjCmd)
	(TclTraceCommandObjCmd): fix possible mem leak in trace info.

2004-02-12  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* win/nmakehlp.c: better macro grepping logic.

2004-02-07  David Gravereaux  <[email protected]>

	* 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	<[email protected]>

	* doc/clock.n:	Removed reference to non-existent [file ctime].

2004-02-05  David Gravereaux  <[email protected]>

	* 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	<[email protected]>

	* generic/tclFileName.c (SkipToChar): Corrected CONST and type-casting
	issues that caused compiler warnings.

2004-02-04  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* generic/tclPathObj.c: fix to [Bug 883143] in file normalization

2004-01-29  Vince Darley  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* doc/file.n: clarified documentation of 'file system' [Bug 883825]
	* tests/fCmd.test: improved test result in failure case.

2004-01-22  Vince Darley  <[email protected]>

	* 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 <[email protected]>

	* doc/Panic.3:	Mentions of 'panic' and 'panicVA' removed from the
	documentation.

2004-01-21  Vince Darley  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* generic/tclCompExpr.c (CompileLandOrLorExpr): cosmetic changes.

2004-01-12  Miguel Sofer <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclStubLib.c: Corrected a typo in "missing Stubs table
	pointer."

2005-12-27  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/Tcl.n: Clarify what is going on in variable substitution
	following thread on comp.lang.tcl.

2005-12-18  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tcl.m4, unix/configure: Fix sh quoting error reported in
	bash-3.1+ [Bug 1377619] (schafer)

2005-12-12  Kevin B. Kenny  <[email protected]>

	* doc/mathfunc.n: Changed two examples from the incorrect 'tcl::math::'
	to 'tcl::mathfunc::' [Bug 1378818]

2005-12-09  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIO.c (TclFinalizeIOSubsystem): preserve statePtr until we
	retrieve the next statePtr from it.

2005-11-18  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/namespace.test: fix comment

2005-11-14  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/trace.test (trace-8.9): added test to detect leak, see [Bug
	1348775].

2005-11-04  Pat Thoyts  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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
	[email protected] 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclNamesp.c: fix for [Bugs 1338280/1337229]. Thanks Don.
	* tests/trace.test: fix duplicate test numbers

2005-10-31  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/foreach.test (foreach-8.1): added test for [Bug 1189274]

2005-10-22  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c (INST_INCR_*): fixed [Bug 1334570]. Obj leak
	detection and patch by Eric Melbardis.

2005-10-21  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c:	Restored some optimizations of the
	INST_INCR_SCALAR1_IMM opcode.

2005-10-14  Zoran Vasiljevic  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TclIncrObj, TclExecuteByteCode): Tidied up a
	couple of infelicitous do {...} while(0) constructs.

2005-10-14  Pat Thoyts  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclPathObj.c (SetFsPathFromAny): TclGetString macro must not
	be combined with post-increment arguments. [Bug 1325099]

2005-10-12  Kevin Kenny  <[email protected]>

	* generic/tclExecute.c (Tcl_ExecuteByteCode, TclIncrObj): Several
	common cases inlined in hopes of gaining a little performance in [incr]

2005-10-10  Miguel Sofer  <[email protected]>

	* generic/tclCompCmds.c: New convenience macro CompileTokens().

2005-10-10  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]> on comp.lang.tcl

2005-10-10  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c: Fixing errors in last commit. (Two commits, the
	second removes wrong comment).

2005-10-09  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[kennykb-numerics-branch]

	* generic/tclExecute.c:	Improved performance of INST_RSHIFT and
	INST_LSHIFT.

2005-10-05  Don Porter  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclMain.c: Separate encoding conversion of command line
	arguments from list formatting. [Bug 1306162].

2005-09-30  Don Porter  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[kennykb-numerics-branch] Merge updates from HEAD.

2005-09-26  Kevin Kenny  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* doc/ParseCmd.3: copy/paste fix [Bug 1292427]

2005-09-15  Don Porter  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[kennykb-numerics-branch]	Merge updates from HEAD.

2005-09-09  Kevin Kenny  <[email protected]>

	* generic/tclStringObj.c:  Added two missing casts to silence messages
	from MSVC6.

2005-09-09  Don Porter  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclObj.c (pendingObjDataKey): Added missing 'static' to stop
	symbol from leaking outside the Tcl library. [Bug 1263012]

2005-09-02  Don Porter  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[kennykb-numerics-branch]	Merge updates from HEAD.

	* generic/tclBasic.c:	Restored round(.) to the Tcl 8.4 rules.

2005-08-29  Kevin Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* unix/configure.in:
	* win/configure: Regen.
	* win/configure.in: Update minimum autoconf version to 2.59.

2005-08-23  Kevin Kenny  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* unix/tclConfig.h.in: autoheader-2.59.

2005-08-22  Don Porter  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclPathObj.c: fix to [file rootname] bug in optimized code
	path reported on comp.lang.tcl.

2005-08-08  Don Porter  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[kennykb-numerics-branch]
	* generic/tclObj.c:	Rewrote Tcl_GetDoubleFromObj().

2005-08-05  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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	<[email protected]>

	[kennykb-numerics-branch] Updated from HEAD

2005-07-30  Daniel Steffen  <[email protected]>

	* unix/tclLoadDyld.c (TclpDlopen, TclpLoadMemory): workarounds for
	bugs/changes in behaviour in Mac OS X 10.4 Tiger.

2005-07-29  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* win/README: Update link to msys_mingw8.zip.

2005-07-28  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (INST_DICT_*): stop 2 compiler warnings for
	uninitialised variables.

2005-07-23  Donal K. Fellows  <[email protected]>

	* generic/tclExecute.c (TEBC:INST_DICT_INCR_IMM): Fix the incrementor
	to work correctly with wide values.

2005-07-21  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclStrToD.c (RefineResult):  Plugged a stupid memory leak in
	RefineResult (called from Tcl_StrToD). [Tk Bug 1227781]

2005-07-15  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* doc/lsearch.n: Clarify documentation of -exact option; wording was
	open to misinterpretation by non-English speakers.

2005-07-11  Donal K. Fellows  <[email protected]>

	* generic/tclExecute.c: General style cleanup.

2005-07-08  Mo DeJong  <[email protected]>

	* 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	<[email protected]>

	* generic/tclLink.c:	Simplified LinkTraceProc [Bug 1208108].

2005-07-05  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* library/auto.tcl:	Make file safe to re-[source] without
	destroying registered auto_mkindex_parser hooks.

2005-06-23  Kevin Kenny  <[email protected]>

	* 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  <[email protected]>

	* tools/tcltk-man2html.tcl: fixed useversion glob pattern to accept
	multi-digit patchlevels.

2005-06-22  Don Porter	<[email protected]>

	* win/tclWinFile.c: Potential buffer overflow. [Bug 1225571] Thanks to
	Pat Thoyts for discovery and fix.

2005-06-22  Kevin Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclFCmd.c: correct fix to file mkdir 2005-06-09 [Bug 1219176]

2005-06-12  Donal K. Fellows  <[email protected]>

	* generic/tclCompCmds.c: Factor out some common idioms into named forms
	for greater clarity.

2005-06-10  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	*** 8.5a3 TAGGED FOR RELEASE ***

	* unix/Makefile.in (dist): add libtommath

2005-06-03  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* macosx/Makefile: fixed 'embedded' target.

2005-06-02  Jeff Hobbs	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinThrd.c: Fixed [Bug 1204064]

2005-05-30  Donal K. Fellows  <[email protected]>

	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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclCmdMZ.c (Tcl_TimeObjCmd): add necessary cast

2005-05-25  Don Porter	<[email protected]>

	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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* doc/mathfunc.n: Changed NAME line to match the name of the page.

2005-05-11  Kevin Kenny  <[email protected]>

	[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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	Merged all changes on kennykb-numerics-branch back into the HEAD.
	TIP's 132 and 232 are now Final.

2005-05-10  Kevin Kenny  <[email protected]>

	[kennykb-numerics-branch] Merged changes from HEAD.

2005-05-10  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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	<[email protected]>

	* 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  <[email protected]>

	[kennykb-numerics-branch] Merged with HEAD.

2005-05-05  Kevin B. Kenny  <[email protected]>

	* win/tclWinThrd.c:  Corrected a compilation error on the
			     --enable-threads configuration.

2005-05-05  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixNotfy.c: applied dkf's tkMacOSXNotify.c cleanup changes.

2005-04-29  Don Porter	<[email protected]>

	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	<[email protected]>

	* tests/unixInit.test (7.1): Alternative fix for the 2004-11-11 commit.

2005-04-27  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[kennykb-numerics-branch] Merged with HEAD.

	* doc/CrtMathFunc.n:		Revised documentation for TIP 232

2005-04-25  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* library/init.tcl:	Use "ni" and "in" operators.

2005-04-25  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c: fix for [Bug 1189274].

2005-04-24  Don Porter	<[email protected]>

	* generic/tclLiteral.c:	Silence compiler warnings.
	* generic/tclObj.c:	[Bug 1188863].

2005-04-22  Don Porter	<[email protected]>

	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	<[email protected]>

	* 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  <[email protected]>

	[kennykb-numerics-branch]
	* doc/expr.n:
	* doc/mathfunc.n (new file):	Revised documentation for TIP 232

2005-04-20  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* generic/tclFileName.c: Silenced a compiler warning about '/*' within
	a comment.

2005-04-19  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/Var.c (Tcl_ArrayObjCmd - ARRAY_NAMES): fix Tcl_Obj leak. [Bug
	1084111]

2005-04-16  Zoran Vasiljevic  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: missing semicolons caused failure to compile
	with TCL_COMPILE_DEBUG.

2005-04-13  David Gravereaux  <[email protected]>

	* 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
	<[email protected]> 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>
	on comp.lang.tcl that the current documentation was not clear.

2005-04-13  Miguel Sofer  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclBasic.c (TclObjInvoke):	Plug memory leak. [Bug 1180368]

2005-04-09  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c: fix possible leak of expansion Tcl_Objs

2005-04-09  Daniel Steffen  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: small opts in obj handling

2005-04-02  Miguel Sofer  <[email protected]>

	* generic/tclVar.c: converted a few function calls to macros.

2005-04-01  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (INST_JUMP_TRUE/FALSE): replaced "test and
	branch" with "compute index into table"

2005-03-30  Donal K. Fellows  <[email protected]>

	* doc/FileSystem.3: Defined loadHandle argument. [Bug 1172401]

2005-03-29  Jeff Hobbs	<[email protected]>

	* win/tcl.m4, win/configure: do not require cygpath in macros to allow
	msys alone as an alternative.

2005-03-24  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* unix/tcl.m4:	  Updated the OpenBSD configuration and regenerated
	* unix/configure: the configure script.

2005-03-15  Kevin B. Kenny  <[email protected]>

	[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  <[email protected]>

	* generic/tclExecute.c: fixed INST_PUSH1's debugging code (wrong obj
	ref passed to TRACE_WITH_OBJ).

2005-03-14  Miguel Sofer  <[email protected]>

	* generic/tclCompile.c: fixed INST_RETURN's stack effect in
	tclInstructionTable (-1 instead of -2)

2005-03-10  Miguel Sofer  <[email protected]>

	* generic/tclCompCmds.c: removed debugging line

2005-03-10  Don Porter	<[email protected]>

	* 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  <[email protected]>

	[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	<[email protected]>

	* win/makefile.vc: clarify necessary defined vars that can come from
	MSVC or the Platform SDK.

2005-03-07  Donal K. Fellows  <[email protected]>

	* doc/string.n: Minor typo. [Bug 1158247]

2005-03-07  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	* doc/CrtSlave.3: Changed to Tcl_Object to Tcl_Obj in the man page.

2005-02-24  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* doc/CrtChannel.3 (THREADACTIONPROC): Formatting fix. [Bug 1149605]

2005-02-17  Jeff Hobbs	<[email protected]>

	* win/tclWinFCmd.c (TraverseWinTree): use wcslen on wchar, not
	Tcl_UniCharLen.

2005-02-16  Miguel Sofer  <[email protected]>

	* doc/variable.n: fix for [Bug 1124160], variables are detected by
	[info vars] but not by [info locals].

2005-02-11  Jeff Hobbs	<[email protected]>

	* 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  <[email protected]>

	* tests/basic.test (basic-26.3): new test

2005-02-10  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* generic/tclFileName.c: fix for test failures introduced on 2005-01-17
	[Bug 1119092]

2005-02-10  Donal K. Fellows  <[email protected]>

	* doc/binary.n: Made the documentation of sign bit masking and [binary
	scan] consistent. [Bug 1117017]

2005-02-08  David N. Welton  <[email protected]>

	* doc/CrtChannel.3: Typo: return->returns.

2005-02-06  Kevin B. Kenny  <[email protected]>

	[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  <[email protected]>

	* doc/Thread.3: One-word grammar fix.

2005-02-05  David N. Welton  <[email protected]>

	* 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  <[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	[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	<[email protected]>

	* generic/tclExecute.c (TclCompEvalObj): Removed stray statement left
	behind in prior code reorganization.

2005-01-31  Don Porter	<[email protected]>

	* unix/configure:	autoconf-2.57

2005-01-30  Joe English  <[email protected]>

	* 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	<[email protected]>

	* unix/configure, unix/tcl.m4: add solaris 64-bit gcc build support.
	[Bug 1021871]

2005-01-28  Donal K. Fellows  <[email protected]>

	* tests/expr-old.test (expr-old-37.2): Added test for [Bug 1109484]

2005-01-27  Jeff Hobbs	<[email protected]>

	* generic/tclBasic.c (Tcl_ExprBoolean, Tcl_ExprDouble)
	(Tcl_ExprLong): Fix to recognize Tcl_WideInt type. [Bug 1109484]

2005-01-26  Andreas Kupries  <[email protected]>

	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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/FileSystem.3: Add missing ARGUMENTS section definitions for
	arguments to Tcl_FSLink. [Bug 1106272]

2005-01-21  Kevin B. Kenny  <[email protected]>

	[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  <[email protected]>

	[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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* tests/winDde.test: Fixed broken test result.

2005-01-05  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* doc/dict.n: Clarified meaning of dictionary values following
	discussion on comp.lang.tcl.

2007-12-26  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdIL.c: Speed patch for lsort. [Patch 1856994]

2007-12-21  Miguel Sofer  <[email protected]>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd, Tcl_LsearchObjCmd): Avoid
	calling SelectObjFromSublist when there are no sublists.

2007-12-21  Miguel Sofer  <[email protected]>

	* 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	<[email protected]>

	*** 8.5.0 TAGGED FOR RELEASE ***

	* changes:		Updated for 8.5.0 release.

2007-12-19  Jeff Hobbs	<[email protected]>

	* 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	<[email protected]>

	* changes:		Updated for 8.5.0 release.

2007-12-18  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* changes:		Updated for 8.5.0 release.

2007-12-17  Miguel Sofer  <[email protected]>

	* 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	<[email protected]>

	* generic/tclIOUtil.c (FsAddMountsToGlobResult): fix the tail
	conversion of vfs mounts. [Bug 1602539]

	* win/README: updated notes

2007-12-14  Pat Thoyts	<[email protected]>

	* tests/winFile.test: Fixed tests for win2k with long machine name

2007-12-14  Pat Thoyts <[email protected]>

	* win/nmakehlp.c:  Support compilation with MSVC9 for AMD64.
	* win/makefile.vc:

2007-12-13  Donal K. Fellows  <[email protected]>

	* doc/trace.n: Clarified documentation of enterstep and leavestep
	traces, including adding example. [Bug 614282, 1701540, 1755984]

2007-12-12  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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	 <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* doc/namespace.n:	Documentation for zero-argument form of
	[namespace import] (TIP 261) [Bug 1596416]

2007-12-06  Jeff Hobbs	<[email protected]>

	* generic/tclInt.h: add TclGetChannelFromObj decl
	(TclMatchIsTrivial): simplify TclMatchIsTrivial to remove ] check.

2007-12-06  Donal K. Fellows  <[email protected]>


	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdIL.c (Tcl_LsearchObjCmd): Prevent shimmering crash
	when -exact and -integer/-real are mixed. [Bug 1844789]

2007-12-03  Donal K. Fellows  <[email protected]>

	* unix/tclUnixChan.c (CreateSocketAddress): Add extra #ifdef-fery to
	make code compile on BSD 5. [Bug 1618235, again]

2007-12-03  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* win/configure, win/tcl.m4 (LIBS_GUI): remove ole32.lib oleaut32.lib

2007-12-03  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* generic/tclIO.c: -eofchar must support no eofchar.

2007-11-27  Miguel Sofer  <[email protected]>

	* generic/tclBasic.c: remove unneeded call in Tcl_CreateInterp, add
	comments.

2007-11-27  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix bug in [dict
	append] compiler which caused strange stack corruption. [Bug 1837392]

2007-11-23  Andreas Kupries  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdMZ.c (String*Cmd, TclInitStringCmd): Rebuilt [string]
	* generic/tclCompCmds.c (TclCompileString*Cmd): as an ensemble.

2007-11-22  Donal K. Fellows  <[email protected]>

	* generic/tclDictObj.c (Dict*Cmd,TclInitDictCmd): Rebuilt the [dict]
	* generic/tclCompCmds.c (TclCompileDict*Cmd): command as an ensemble.

2007-11-22  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	*** 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	 <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode:INST_EXIST_*): Fix read
	traces not firing on non-existent array elements. [Bug 1833522]

2007-11-16  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* macosx/Tcl.xcodeproj/project.pbxproj: add new chanio.test.
	* macosx/Tcl.xcode/project.pbxproj:

2007-11-14  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclCompCmds.c (TclCompileRegexpCmd): clean up comments, only
	free dstring on OK from TclReToGlob.
	(TclCompileSwitchCmd): simplify TclReToGlob usage.

2007-11-14  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* generic/regcomp.c:	Convert optst() from expensive no-op to a
	cheap no-op.

2007-11-13  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>. 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclUtil.c (Tcl_ConcatObj): optimise for some of the
	concatenees being empty objs. [Bug 1447328]

2007-10-28  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/regc_lex.c (lexescape): Close off one of the problems
	mentioned in [Bug 1810264].

2007-10-27  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* tools/tcltk-man2html.tcl (make-man-pages, htmlize-text)
	(process-text): Make the man->HTML scraper work better.

2007-10-26  Don Porter	<[email protected]>

	*** 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile.c:	  Fix comments.
	* generic/tclExecute.c:

2007-10-18  David Gravereaux <[email protected]>

	* tools/mkdepend.tcl: sort the dep list for a more humanly readable
	output.

2007-10-18  Don Porter	<[email protected]>

	* 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 <[email protected]>

	* tools/mkdepend.tcl:	Improved defense from malformed object list
	infile.

2007-10-17  Donal K. Fellows  <[email protected]>

	* tools/man2html2.tcl: Convert .DS/.DE into HTML tables, not
	preformatted text.

2007-10-17  Kevin B. Kenny  <[email protected]>

	* 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 <[email protected]>

	* win/makefile.vc: removed old dependency cruft that is no longer
	needed.

2007-10-15  Don Porter	<[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* generic/tclParse.c (Tcl_ParseBraces): fix for possible read after
	the end of buffer. [Bug 1813528] (Joe Mistachkin)

2007-10-14  David Gravereaux <[email protected]>

	* tools/mkdepend.tcl (new):  Initial stab at generating automatic
	* win/makefile.vc:	     dependencies.

2007-10-12  Pat Thoyts	<[email protected]>

	* 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 <[email protected]>

	* win/makefile.vc:  Fixed my bad spelling mistakes from years back.
	Dedependency, duh!  Rather funny.

2007-10-11  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* generic/tclObj.c: remove superfluous #include of tclCompile.h

2007-10-08  George Peter Staplin <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	[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  <[email protected]>

	* library/tclIndex: Added 'tcl::tm::path' to the tclIndex. This fixes
	[Bug 1806422] reported by Don Porter.

2007-09-25  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	*** 8.5b1 TAGGED FOR RELEASE ***

	* changes: updates for 8.5b1 release.

2007-09-19  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* generic/tclStubLib.: Replaced isdigit with internal implementation.

2007-09-18  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* win/makefile.vc: Add crt flags for tclStubLib now it uses C-library
			   functions.

2007-09-17  Joe English	 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (Tcl_CreateObjCommand): Only invalidate along the
	namespace path once; that is enough. [Bug 1519940]

2007-09-14  Daniel Steffen  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclLink.c (Tcl_UpdateLinkedVar): guard against var being
	unlinked. [Bug 1740631] (maros)

2007-09-10  Miguel Sofer  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c (Tcl_SetVar2, TclPtrSetVar): [Bug 1710710] fixed
	correctly, reverted fix of 2007-05-01.

2007-09-08  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile.c: replaced copy loop that tripped some compilers
	with memmove. [Bug 1780870]

2007-08-23  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (TEBC): disable the new shortcut to frequent
	INSTs for debug builds. REVERTED (collision with alternative fix)

2007-08-21  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c (Overflowing, TclIncrObj, TclExecuteByteCode):
	Encapsulate Miguel's last change in a more mnemonic macro.

2007-08-19  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclExecute.c: Provide DECACHE/CACHE protection to the
	* tests/trace.test:	Tcl_LogCommandInfo() call. [Bug 1773040]

2007-08-12  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.h: remove redundant ops in TclNewStringObj macro.

2007-08-10  Miguel Sofer  <[email protected]>

	* generic/tclInt.h: fix the TclSetVarNamespaceVar macro, was causing a
	leak.

2007-08-10  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclProc.c (InitLocalCache): reference firstLocalPtr via
	procPtr. codePtr->procPtr == NULL exposed by tbcload.

2007-08-08  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/word.tcl: Rewrote for greater efficiency. [Bug 1764318]

2007-08-01  Pat Thoyts	<[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c (TclCleanupVar): fix [Bug 1765225], thx Larry
	Virden.

2007-07-31  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixChan.c (SET_BITS, CLEAR_BITS): Added macros to make this
	file clearer.

2007-07-24  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* generic/tclCompExpr.c:	Removed unused arguments and variables

2007-07-17  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* generic/tclCompExpr.c:	Factored out, corrected, and commented
	common code for reporting syntax errors in LEAF elements.

2007-07-11  Miguel Sofer  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* library/init.tcl (unknown):	Corrected inconsistent error message
	in interactive [unknown] when empty command is invoked. [Bug 1743676]

2007-07-05  Miguel Sofer  <[email protected]>

	* generic/tclNamesp.c (SetNsNameFromAny):
	* generic/tclObj.c (SetCmdNameFromAny): Avoid unnecessary
	ckfree/ckalloc when the old structs can be reused.

2007-07-04  Miguel Sofer  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c (UnsetVarStruct): fix possible segfault.

2007-06-27  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* generic/tclBasic.c (TclEvalEx):	Moved some arrays from the C
	stack to the Tcl stack.

2007-06-26  Miguel Sofer  <[email protected]>

	* generic/tclVar.c (UnsetVarStruct): more streamlining.

2007-06-25  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* generic/tclVar.c (UnsetVarStruct): fixing incomplete change, more
	streamlining.

2007-06-24  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tcl.h, generic/tclCompile.h, generic/tclCompile.c: Remove
	references in comments to obsolete {expand} notation. [Bug 1740859]

2007-06-20  Miguel Sofer  <[email protected]>

	* generic/tclVar.c: streamline namespace vars deletion: only compute
	the variable's full name if the variable is traced.

2007-06-20  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* tools/tcltk-man2html.tcl: revamp of html doc output to use CSS,
	standardized headers, subheaders, dictionary sorting of names.

2007-06-18  Jeff Hobbs	<[email protected]>

	* tools/tcltk-man2html.tcl: clean up copyright merging and output.
	clean up coding constructs.

2007-06-18  Miguel Sofer  <[email protected]>

	* 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	<[email protected]>

	* generic/tclBasic.c (TclEvalEx,TclEvalObjEx):	Moved the CmdFrame off
	the C stack and onto the Tcl stack.

2007-06-17  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* macosx/Tcl.xcodeproj/project.pbxproj: add new Tclsh-Info.plist.in.

2007-06-08  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclParse.c: fix for uninit read. [Bug 1732414]

2007-06-06  Daniel Steffen  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.h:
	* generic/tclExecute.c: Tcl-stack reform, [Patch 1701202]

2007-06-03  Daniel Steffen  <[email protected]>

	* unix/Makefile.in: add datarootdir to silence autoconf-2.6x warning.

2007-05-30  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* unix/tclUnixThrd.c (Tcl_JoinThread): fix for 64-bit handling of
	pthread_join exit return code storage. [Bug 1712723]

2007-05-22  Don Porter	<[email protected]>

	[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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tcl.decls: workaround 'make checkstubs' failures from
	tclStubLib.c MODULE_SCOPE revert. [Bug 1716117]

2007-05-16  Joe English	 <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* generic/tclInt.h: Removed TclEvalObjEx and TclGetSrcInfoForPc from
	tclInt.h now they are in the internal stubs table.

2007-05-09  Don Porter	<[email protected]>

	* generic/tclInt.h:	TclFinalizeThreadAlloc() is always defined, so
	make sure it is also always declared (with MODULE_SCOPE).

2007-05-09  Daniel Steffen  <[email protected]>

	* 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	<[email protected]>

	[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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* unix/Makefile.in (dist): add platform library package to src dist

2007-04-24  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile.c (TclFreeCompileEnv): Tip 280's new field
	extCmdMapPtr was not being freed. [Bug 1705778, leak #1]

2007-04-23  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclListObj.c (SetListFromAny): avoid discarding internal
	reps of objects converted to singleton lists. [Patch 738900]

2007-04-20  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: fixed checkInterp logic [Bug 1702212]

2007-04-16  Donal K. Fellows  <[email protected]>

	* various (including generic/tclTest.c): Complete the purge of K&R
	function definitions from manually-written code.

2007-04-15  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: removed some code at INST_EXPAND_SKTOP that
	duplicates functionality already present at checkForCatch.

2007-04-12  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompCmds.c: moved all exceptDepth management to the
	macros - the decreasing half was managed by hand.

2007-04-10  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile (tclInstructionTable): Fixed bugs in description
	of dict instructions.

2007-04-07  Miguel Sofer  <[email protected]>

	* generic/tclCompile (tclInstructionTable): Fixed bug in description
	of INST_START_COMMAND.

	* generic/tclExecute.c (TEBC): Small code reduction.

2007-04-06  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: INST_INVOKE optimisation. [Patch 1693802]

2007-04-03  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: optimise the lookup of elements of indexed
	arrays.

2007-03-29  Miguel Sofer  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* generic/tclCmdMZ.c (STR_MAP): Replace ckalloc calls with
	TclStackAlloc calls.

2007-03-24  Zoran Vasiljevic <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (DeleteInterpProc): pop the root frame pointer
	before deleting the global namespace [Bug 1658572]

2007-03-23  Kevin B. Kenny  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* generic/tclEnv.c:	Some more ckalloc -> ckrealloc replacements.
	* generic/tclLink.c:

2007-03-20  Kevin B. Kenny  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* doc/regsub.n: Corrected example so that it doesn't recommend
	potentially unsafe practice. Many thanks to Konstantin Kushnir
	<[email protected]> for reporting this.

2007-03-17  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/Makefile.in: Fully qualify LIBRARY_DIR so that `make test` does
	not depend on working dir.

2007-03-15  Mo DeJong  <[email protected]>

	* tests/parse.test: Add two backslash newline parse tests.

2007-03-12  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdIL.c (Tcl_LsortObjCmd): Fix problems with declaration
	positioning and memory leaks. [Bug 1679072]

2007-03-11  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdIL (Tcl_LsortObjCmd): changed fix to [Bug 1675116] to
	use the cheaper TclListObjCopy() instead of Tcl_DuplicateObj().

2007-03-09  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclLink.c (LinkedVar): Added macro to conceal at least some
	of the pointer hackery.

2007-03-02  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* doc/tcltest.n:	Typo fix. [Bug 1663539]

2007-02-20  Pat Thoyts	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/re_syntax.n: Corrected description of 'print' class [Bug
	1614687] and enhanced description of 'graph' class.

2007-02-12  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* win/nmakehlp.c: Properly cleanup after nmakehlp, including the
	* win/makefile.vc: vcX0.pch file.

2007-02-08  Jeff Hobbs	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* generic/tclNamesp.c:	Corrected broken implementation of the
	* tests/namespace.test: TclMatchIsTrivial optimization on [namespace
	children $namespace $pattern].

2007-02-04  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* win/rules.vc: Fix platform specific file copy macros for downlevel
	Windows.

2007-01-29  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIO.c: Added macros to make usage of ChannelBuffers
	clearer.

2007-01-11  Joe English	 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclDate.c: Regenerated to recover a lost fix from patthoyts.
	[Bug 1618523]

2006-12-26  Mo DeJong  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixThrd.c (Tcl_GetAllocMutex, TclpNewAllocMutex): Add
	intermediate variables to shut up unwanted warnings. [Bug 1618838]

2006-12-19  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/string.n: Fix example. [Bug 1615277]

2006-12-12  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/tcltest/tcltest.tcl: use [info frame] for "-verbose line".

2006-12-07  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* tests/exec.test: Fixed line endings (caused win32 problems).

2006-12-06  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* tests/expr.test (expr-47.12): Improved error reporting in hopes of
	having more information to pursue [Bug 1609936].

2006-12-05  Andreas Kupries  <[email protected]>

	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	<[email protected]>

	* 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  <[email protected]>

	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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* doc/file.n: Clarification of [file pathtype] docs. [Bug 1606454]

2006-12-01  Kevin B. Kenny	 <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclExecute.c (TclIncrObj):	Correct failure to detect
	floating-point increment values. Thanks to William Coleda [Bug
	1602991]

2006-11-26  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* unix/tcl.m4 (Linux): --enable-64bit support.	[Patch 1597389]
	* unix/configure: autoconf-2.59			[Bug 1230558]

2006-11-25  Donal K. Fellows  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* doc/apply.n, doc/chan.n: Added examples.

2006-11-15  Don Porter	<[email protected]>

	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  <[email protected]>

	* 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	<[email protected]>

	TIP#261 IMPLEMENTATION

	* generic/tclNamesp.c:	[namespace import] with 0 arguments
	introspects the list of imported commands.

2006-11-13  Kevin B. Kenny  <[email protected]>

	* generic/tclThreadStorage.c (Tcl_InitThreadStorage):
	(Tcl_FinalizeThreadStorage): Silence a compiler warning about
	presenting a volatile pointer to 'memset'.

2006-11-13  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.h, generic/tclInt.decls: Transfer TclPtrMakeUpvar and
	TclObjLookupVar to the internal stubs table.

2006-11-10  Daniel Steffen  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* generic/tclIO.c, generic/tclPkg.c: Style & clarity rewrites.

2006-11-07  Andreas Kupries  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* macosx/Tcl.xcodeproj/project.pbxproj: check autoconf/autoheader exit
	status and stop build if they fail.

2006-11-02  Jeff Hobbs	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* win/rules.vc: Fix for [Bug 1582769] - options conflict with VC2003.

2006-10-31  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* tools/tcltk-man2html.tcl (option-toc): handle any kind of options
	defined toc section (needed for ttk docs)

2006-10-30  Miguel Sofer  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclInterp.c (ApplyObjCmd): fixed bad error in 2006-10-12
	commit: interp released too early. Spotted by mistachkin.

2006-10-16  Miguel Sofer  <[email protected]>

	* tclProc.c (SetLambdaFromAny):
	* tests/apply.test (9.1-9.2): plugged intrep leak [Bug 1578454],
	found by mjanssen.

2006-10-16  Andreas Kupries  <[email protected]>

	* generic/tclBasic.c: Moved TIP#219 cleanup to DeleteInterpProc.

2006-10-16  Daniel Steffen  <[email protected]>

	* 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	<[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* win/nmakehlp.c: Replaced all wnsprintf() calls with snprintf().
	wnsprintf was not in my shwlapi header file (VC++6)

2006-10-11  Don Porter	<[email protected]>

	* generic/tclPkg.c (Tcl_PackageRequireEx):	Corrected crash when
	argument version=NULL passed in.

2006-10-10  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* win/rules.vc: [Bug 1571954] avoid /RTCc flag with MSVC8

2006-10-06  Pat Thoyts	<[email protected]>

	* 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  <[email protected]>

	* library/tm.tcl: Fixed bug in TIP #189 implementation, now allowing
	'_' in module names.

2006-10-05  Jeff Hobbs	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tzdata/: Olson's tzdata2006m.

2006-10-01  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* doc/Eval.3 (TclEvalObjv): added note on refCount management for the
	elements of objv. [Bug 730244]

2006-10-01  Pat Thoyts	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* win/makefile.vc:  Additional compiler flags and amd64 support.
	* win/nmakehlp.c:
	* win/rules.vc:

2006-09-26  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/package.n: Fixed nits reported by Daniel Steffen in the TIP#268
	changes.

2006-09-25  Kevin B. Kenny   <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.h: Moved TIP#268's field 'packagePrefer' to the end
	of the structure, for better backward compatibility.

2006-09-22  Andreas Kupries  <[email protected]>

	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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclUtil.c:	Dropped ParseInteger() routine. TclParseNumber
	covers the task just fine.

2006-09-19  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* unix/Makefile.in (install-libraries): Fixed typo tcltest 2.3.9 ->
	2.3.0.

2006-09-11  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* tests/msgcat.test: Bumped version in auxiliary files as well.
	* doc/msgcat.n:

2006-09-11  Kevin B. Kenny  <[email protected]>

	* 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	<[email protected]>

	* library/msgcat/msgcat.tcl:	Removed some unneeded [uplevel]s.

2006-09-10  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixCompat.c: Fixed conditions for CopyArray/CopyString, and
	CopyHostent. Also fixed bad var names in TclpGetHostByName.

2006-09-07  Zoran Vasiljevic <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* doc/package.n: correct package example

2006-08-31  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* generic/tclParseExpr.c:	Dropped the old expr parser.

2006-08-30  Jeff Hobbs	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/tzdata/America/Havana:      Regenerated from Olson's
	* library/tzdata/America/Tegucigalpa: tzdata2006k.
	* library/tzdata/Asia/Gaza:

2006-08-28  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* generic/tclClock.c (ClockClicksObjCmd): Fix nested macro breakage
	with TCL_MEM_DEBUG enabled. [Bug 1547662]

2006-08-26  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* win/Makefile.in (gdb): Make this target work so that debugging an
	msys build is possible.

2006-08-21  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclCompile.c:		Revised the new set of expression
	* generic/tclParseExpr.c:	parse error messages.

2006-08-16  Don Porter	<[email protected]>

	* generic/tclParseExpr.c:	Replace PrecedenceOf() function with
	prec[] static array.

2006-08-14  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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	<[email protected]>

	* generic/tclEncoding.c:	Replace buffer copy in for loop with
	call to memcpy(). Thanks to afredd. [Patch 1530262]

2006-08-09  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	 <[email protected]>

	* doc/AppInit.3: Fix typo [Bug 1496886]

2006-07-26  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* win/tclWinSock.c:	Correct un-initialized Tcl_DString. Thanks to
	afredd. [Bug 1518166]

2006-07-21  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c:
	* tests/execute.test (execute-9.1): dgp's fix for [Bug 1522803].

2006-07-20  Daniel Steffen  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* generic/tclAsync.c: Made Tcl_AsyncDelete() more tolerant when called
	after all thread TSD has been garbage-collected.

2006-07-05  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclLoadDl.c (TclpDlopen): Workaround for a compiler bug in Sun
	Forte 6. [Bug 1503729]

2006-06-06  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* generic/tcl.h (Tcl_DecrRefCount): use if/else construct to allow
	placement in unbraced outer if/else conditions. (jcw)

2006-05-27  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* generic/tclEvent.c (HandleBgErrors): fix leak. [Coverity issue 86]

2006-05-05  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	*** 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/IntObj.3: Minor review fixes, including better documentation of
	the behaviour of Tcl_GetBignumAndClearObj.

2006-04-17  Don Porter	<[email protected]>

	* doc/IntObj.3: Documentation changes to account for TIP 237 changes.
	* doc/Object.3: [Bug 1446971]

2006-04-12  Donal K. Fellows  <[email protected]>

	* 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	<[email protected]>

	* generic/tclTrace.c:	Stop some interference between enter traces
	* tests/trace.test:	and enterstep traces. [Bug 1458266]

2006-04-07  Don Porter	<[email protected]>

	* generic/tclPathObj.c: Yet another revised fix for the [Bug 1379287]
	* tests/fileSystem.test:	family of path normalization bugs.

2006-04-06  Jeff Hobbs	<[email protected]>

	* generic/tclRegexp.c (FinalizeRegexp): full reset data to indicate
	readiness for reinitialization.

2006-04-06  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: remove unused var and silence gcc warning

2006-03-29  Jeff Hobbs	<[email protected]>

	* win/Makefile.in: convert _NATIVE paths to use / to avoid ".\"
	path-as-escape issue.

2006-03-29  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIOUtil.c: fix to nativeFilesystemRecord comparisons
	(lesser part of [Bug 1064247])

2006-03-27  Pat Thoyts	<[email protected]>

	* win/tclWinTest.c:	Fixes for [Bug 1456373] (mingw-gcc issue)

2006-03-27  Andreas Kupries <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* generic/tclExecute.c: Corrections to INST_EXPON detection of
	overflow to use mp_int calculations.

2006-03-24  Kevin B. Kenny  <[email protected]>

	* generic/tclExecute.c (TclExecuteByteCode): Added a couple of missing
	casts to 'int' that were affecting compilablity on VC6.

2006-03-24  Don Porter	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* win/fCmd.test: add proper test constraints so the new tests don't
	run on Unix.

2006-03-14  Andreas Kupries <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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 <[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	-- 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  <[email protected]>

	* win/tclWinFile.c: previous patch breaks tests, so removed.

2006-03-09  Vince Darley  <[email protected]>

	* 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	<[email protected]>

	* generic/tclExecute.c: Complete missing bit of TIP 215 implementation
	* tests/incr.test:

2006-03-07  Joe English	 <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* 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	<[email protected]>

	* generic/tclIO.c:	Made several routines tolerant of
	* generic/tclIORChan.c: interp == NULL arguments. [Bug 1380662]
	* generic/tclIOUtil.c:

2006-02-09  Don Porter	<[email protected]>

	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  <[email protected]>

	* doc/Encoding.3, doc/encoding.n: Updates due to review at request of
	Don Porter. Mostly minor changes.

2006-02-08  Don Porter	<[email protected]>

	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  <[email protected]>

	* 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	<[email protected]>

	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  <[email protected]>

	* doc/dict.n: Fixed silly bug in example. Thanks to Heiner Marxen
	<[email protected]> for catching this! [Bug 1415725]

2006-01-26  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/string.test (string-12.21): Added test for [Bug 1410553] based
	on original bug report.

2006-01-23  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinFile.c: fix to sharing violation [Bug 1366227]

2006-01-11  Don Porter	<[email protected]>

	* 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  <[email protected]>

	* 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	<[email protected]>

	* generic/tclNamesp.c (NamespaceInscopeCmd):	[namespace inscope]
	* tests/namespace.test: commands were not reported by [info level].
	[Bug 1400572]

2006-01-09  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclZlib.c (Tcl_ZlibStreamPut): Plug a memory leak.

2008-12-27  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/Makefile.in:	Fix build of zlib objects with msvc
	* win/tcl.m4:
	* win/configure:	autoconf-2.59

2008-12-23  Donal K. Fellows  <[email protected]>

	* win/Makefile.in: Handle file extensions correctly. [Bug 2459725]

2008-12-22  Pat Thoyts  <[email protected]>

	*** 8.6b1 TAGGED FOR RELEASE ***

	* win/makefile.vc: Ensure pkgs directories are suitable and quote the
			   paths. [Bug 2458395]

2008-12-22  Joe Mistachkin  <[email protected]>

	* tools/man2help2.tcl: Added support for "\(mi" nroff macro. [Bug
	2330040]

2008-12-22  Pat Thoyts  <[email protected]>

	* win/makefile.vc: Support the pkgs tree in the NMAKE builds.

2008-12-21  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* doc/TclZlib.3: Fix minor typo. [Bug 2455165]

2008-12-20  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* changes:	Updates for 8.6b1 release.

2008-12-20  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclInt.decls: CONSTify TclGetLoadedPackages second param
	* generic/tclLoad.c
	* generic/tclIntDecls.h (regenerated)

2008-12-19  Kevin Kenny  <[email protected]>

	* 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  <[email protected]>

	* win/makefile.vc: Added build of compat/zlib

2008-12-18  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tcl.decls:	VOID -> void
	* generic/tclInt.decls:
	* compat/dlfcn.h:
	* generic/tclDecls.h:	(regenerated)
	* generic/tclIntDecls.h:

2008-12-18  Alexandre Ferrieux  <[email protected]>

	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  <[email protected]>

	* doc/SetChanErr.3: General improvements in nroff rendering and some
	corrections to language issues.

2008-12-17  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tcl.h, generic/tclZlib.c: Removed undocumented flag.

2008-12-16  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBinary.c:	Redefine non-strict decoding to ignore only
	* doc/binary.n:		whitespace. [Bug 2380293]
	* tests/binary.test:

2008-12-15  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	TIP #322 IMPLEMENTATION

	* doc/NRE.3 (new file): Added documentation of the published API for
	Non-Recursive Evaluation (NRE).

2008-12-11  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/zlib.test: Start of test suite for zlib command.

2008-12-11  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* library/tzdata/*: Update from Olson's tzdata2008i.

2008-12-10  Alexandre Ferrieux  <[email protected]>

	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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinPipe.c (TclpOpenTemporaryFile): Avoid an infinite loop due
	to GetTempFileName/CreateFile interaction. [Bug 2380318]

2008-12-03  Don Porter  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclParse.c:  Coding standards fixups.

2008-12-01  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIndexObj.c:   Eliminate warning: unused variable
	* generic/tclTest.c:	   A few more (harmless) Tcl_SetResult
				   eliminations.

2008-11-26  Kevin B. Kenny  <[email protected]>

	* 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 <[email protected]>

2008-11-25  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tools/tcltk-man2html.tcl: Improvements to tackle tricky aspects of
	cross references and new entities to map. [Bug 2330040]

2008-11-19  Jan Nijtmans  <[email protected]>

	* generic/tclThreadTest.c: Convert Tcl_SetResult(......, TCL_DYNAMIC)
	to Tcl_SetResult(......, TCL_VOLATILE), in preparation for TIP #340

2008-11-17  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/registry.test: Use HKCU to avoid requiring admin access for
	registry testing on Vista/Server2008

2008-11-11  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* doc/platform_shell.n: Fixed [Bug 2255235], reported by Ulrich
	* library/platform/pkgIndex.tcl: Ring <[email protected]>.
	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclOO.h (TCLOO_VERSION): Bump version of TclOO.

2008-10-31  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdAH.c (ForNextCallback): handle TCL_CONTINUE in the for
	body. [Bug 2186888]

2008-10-22  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* generic/tclProc.c:	Reset -level and -code values to defaults
	after they are used. [Bug 2152286]

2008-10-19  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclOO.decls:		CONST -> const.
	* generic/tclOODecls.h:		(regenerated)
	* generic/tclOOIntDecls.h:	(regenerated)

2008-10-17  Andreas Kupries  <[email protected]>

	* generic/tclIORTrans.c (DeleteReflectedTransformMap): Removed debug
	output in C++ comment.

2008-10-17  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/binary.n: Formatting fix.

2008-10-14  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 8.6a3 TAGGED FOR RELEASE ***

	* changes:	Updates for 8.6a3 release.

2008-10-10  Donal K. Fellows  <[email protected]>

	* generic/tclOODefineCmds.c (TclOODefineUnexportObjCmd)
	(TclOODefineExportObjCmd): Corrected export/unexport record synthesis.
	[Bug 2155658]

2008-10-08  Jan Nijtmans  <[email protected]>

	* unix/tclUnixChan.c:	Fix minor compiler warning.
	* unix/tcl.m4:		Fix for [Bug 2073255]
	* unix/configure:	Regenerated

2008-10-08  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/binary.n: Added better documentation of the [binary encode] and
	[binary decode] subcommands.

2008-10-07  Miguel Sofer  <[email protected]>

	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  <[email protected]>

	* doc/chan.n, doc/transchan.n: Documented the channel transformation
	API of TIP #230.

2008-10-06  Pat Thoyts  <[email protected]>

	* tests/winFCmd.test: Fixed some erroneous tests on Vista+.
	* generic/tclFCmd.c: Fix constness for msvc of last commit

2008-10-06  Joe Mistachkin  <[email protected]>

	* tools/man2tcl.c: Added missing line from patch by Harald Oehlmann.
	[Bug 1934200]

2008-10-05  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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 ([email protected]) 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIndexObj.c (TclInitPrefixCmd): Make the [tcl::prefix]
	into an exported command. [Bug 2144595]

2008-10-04  Donal K. Fellows  <[email protected]>

	* generic/tclCmdIL.c (InfoFrameCmd):	Improved hygiene of result
	* generic/tclRegexp.c (TclRegAbout):	handling.

2008-10-04  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	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  <[email protected]>

	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  <[email protected]>

	* generic/tclBasic.c:	   Fix the numLevels computations on
	* generic/tclInt.h:	   coroutine yield/resume
	* tests/unsupported.test:

2008-09-27  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* generic/tclOO.h (TCLOO_VERSION): Bump the version.

2008-09-25  Don Porter  <[email protected]>

	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  <[email protected]>

	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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* doc/chan.n: Clean up paragraph order.

2008-09-18  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/init.tcl: Export min and max commands from the mathfunc
	namespace. [Bug 2116053]

2008-09-16  Joe Mistachkin  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/append.test, appendComp.test, cmdAH.test: Use the powers of
	tcltest2 to make these files simpler.

2008-09-07  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* doc/namespace.n: Fix [Bug 2098441]

2008-09-04  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/socket.test: Rewrote so as to use tcltest2 better.

2008-09-01  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c:
	* generic/tclExecute.c: Set special errocodes: COROUTINE_BUSY,
	COROUTINE_CANT_YIELD, COROUTINE_ILLEGAL_YIELD.

2008-08-22  Don Porter  <[email protected]>

	*** 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  <[email protected]>

	* generic/tclBasic.c:	  Previous fix, now done right.
	* generic/tclCmdIL.c:
	* generic/tclInt.h:
	* tests/unsupported.test:

2008-08-21  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclProc.c (Tcl_DisassembleObjCmd): Added ability to
	disassemble TclOO methods. The code to do this is very ugly.

2008-08-21  Pat Thoyts  <[email protected]>

	* generic/tclOOMethod.c: Added casts to make MSVC happy
	* generic/tclBasic.c:

2008-08-20  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* generic/tclTest.c (TestconcatobjCmd):	Fix use of internal-only
	TclInvalidateStringRep macro. [Bug 2057479]

2008-08-17  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: Better cmdFrame management

2008-08-14  Don Porter  <[email protected]>

	* tests/fileName.test:	Revise new tests for portability to case
	insensitive filesystems.

2008-08-14  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* tests/nre.test: Added test for large {*}-expansion effects

2008-08-13  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* generic/tclOOInfo.c (InfoObjectDefnCmd, InfoObjectMixinsCmd):
	Fix # args displayed. [Bug 2048676]

2008-08-08  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/http/http.tcl: CRC field from zlib data should be treated as
	unsigned for 64bit support. [Bug 2046846]

2008-08-10  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c:	Slight cleanup
	* generic/tclCompile.h:
	* generic/tclExecute.c:

2008-08-09  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* changes:	Updates for 8.6a2 release.

2008-08-08  Kevin Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tclUnixChan.c: Streamline async connect logic [Patch 1994512]

2008-08-05  Miguel Sofer  <[email protected]>

	* generic/tclExecute.c: Fix for [Bug 2038069] by dgp.
	* tests/execute.test:

2008-08-04  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclOOMethod.c (PushMethodCallFrame): Remove hack that should
	have gone when this code was merged into Tcl.

2008-07-27  Jan Nijtmans  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclBasic.c (GetCommandSource): Added comment with
	explanation and warning for waintainers.

2008-07-22  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/*.c: Fix [2021443] inconsistant "wrong # args" messages
	* win/tclWinReg.c
	* win/tclWinTest.c
	* tests/*.test

2008-07-21  Alexandre Ferrieux  <[email protected]>

	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  <[email protected]>

	* generic/tclFCmd.c:  Inodes on windows are unreliable. [Bug 2015723]
	* tests/winFCmd.test: test rename with inode collision

2008-07-21  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* tests/fileName.test: Repaired the failing test fileName-15.7 from
	dkf's commit earlier today.

2008-07-20  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclOOBasic.c (TclOO_Object_Eval, FinalizeEval): NRE-enable
	the oo::object.eval method.

2008-07-18  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinThrd.c: Test for TLS_OUT_OF_INDEXES to make certain that
	thread key creation is successful.

2008-07-16  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCmdIL.c (InfoFrameCmd): Fixed unsafe idiom of setting
	the interp result found by Don Porter.

2008-07-07  Donal K. Fellows  <[email protected]>

	* doc/regexp.n, doc/regsub.n: Correct examples. [Bug 1982642]

2008-07-06  Donal K. Fellows  <[email protected]>

	* doc/lindex.n: Improve examples.

2008-07-03  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/ObjectType.3: Clean up typedef formatting.

2008-06-30  Don Porter  <[email protected]>

	* doc/ObjectType.3:	Updated documentation of the Tcl_ObjType
	struct to match expectations of Tcl 8.5. [Bug 1917650]

2008-06-30  Alexandre Ferrieux  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclPathObj.c:	 Plug memory leak in [Bug 1999176] fix. Thanks
	to Rolf Ade for detecting.

2008-06-29  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 8.6a1 TAGGED FOR RELEASE ***

	* changes:	Updates for 8.6a1 release.

	* generic/tclOO.h:	Bump to TclOO 0.5.

2008-06-25  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* win/rules.vc: Fix versions of dde and registry dlls
	* win/makefile.vc: Fix problem building with staticpkg option

2008-06-24  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* doc/fileevent.n: Fix examples and comment on eof use. [Bug 1995063]

2008-06-23  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclClock.c (ClockConvertlocaltoutcObjCmd): Removed left
	over debug output.

2008-06-17  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclEncoding.c(UtfToUtfProc): Avoid unwanted sign extension
	when converting incomplete UTF-8 sequences. See [Bug 1908443] for
	details.

2008-06-10  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIORTrans.c (ReflectInput): Fixed a bug triggered by Pat
	Thoyts <[email protected]>. 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  <[email protected]>

	* generic/tclOOCall.c (TclOOGetSortedMethodList): Plug memory leak
	that occurred when all methods were hidden. [Bug 1987817]

2008-06-08  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	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  <[email protected]>

	* generic/tclBinary.c: TIP #317 implementation
	* tests/binary.test:

2008-06-02  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* tests/io.test (io-53.9): Need to close chan before removing file.

2008-05-26  Donal K. Fellows  <[email protected]>

	* win/makefile.bc:		    Remove deprecated winhelp target.
	* win/Makefile.in, win/makefile.vc: It didn't work correctly anyway.

2008-05-23  Andreas Kupries  <[email protected]>

	* win/tclWinChan.c (FileWideSeekProc): Accepted a patch by Alexandre
	Ferrieux <[email protected]> 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 <[email protected]>
	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile.c: Fix crash with tcl_traceExec. Found and fixed
	by Alexander Pasadyn. [Bug 1964803]

2008-05-15  Pat Thoyts  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* */*.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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/Ensemble.3: Fix a typo: s/defiend/defined/
	Thanks to hat0 for spotting this.

2008-04-16  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIO.c (CopyData):	Applied another patch by Alexandre
	* io.test (io-53.8a):		Ferrieux <[email protected]>,
	* 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  <[email protected]>

	* unix/Makefile.in:	Adjust tclDTrace.h dependencies for removal
				of tclStubLib.o from TCL_OBJS. [Bug 1942795]

2008-04-14  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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
	<[email protected]>, with modifications from me to
	separate overflow from true negative value. Extended testsuite. [Bug
	1557855]

2008-04-09  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c: Added comments to the alignment macros used in
	GrowEvaluationStack() and friends.

2008-04-08  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* 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
	<[email protected]> for the patch. [Bug 1350564]

2008-04-07  Reinhard Max  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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
	<[email protected]> for report and patch.

2008-04-02  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIO.c (CopyData): Applied patch for fcopy problem [Bug
	780533], with many thanks to Alexandre Ferrieux
	<[email protected]> 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/tcl.m4 (SunOS-5.1x): Fix 64bit support for Sun cc. [Bug
	1921166]

	* unix/configure: autoconf-2.59

2008-03-26  Don Porter  <[email protected]>

	* changes:		Updated for 8.5.2 release.

2008-03-24  Pat Thoyts  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclExecute.c:	Patch from Miguel Sofer to correct the
	alignment of memory allocated by GrowEvaluationStack(). [Bug 1914503]

2008-03-18  Andreas Kupries  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclTest.c:  Ignore the return value of write() when we are
	* unix/tclUnixPipe.c: about to exit anyways.

2008-03-13  Daniel Steffen  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/info.n: Replaced {expand} with {*}.

2008-03-12  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/configure.in: Add AC_HEADER_STDC to support msys/win64.

2008-03-06  Donal K. Fellows  <[email protected]>

	* doc/namespace.n: Minor tidying up. [Bug 1909019]

2008-03-04  Don Porter  <[email protected]>

	* tests/execute.test (6.3,4):	Added tests for [Bug 1899164].

2008-03-03  Reinhard Max  <[email protected]>

	* unix/tclUnixChan.c: Fix mark and space parity on Linux, which uses
	CMSPAR instead of PAREXT.

2008-03-02  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* library/http/http.tcl: [Bug 705956] - fix inverted logic when
	cleaning up socket error in geturl.

2008-02-27  Kevin B. Kenny  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* generic/tclIORChan.c (enum MethodName),
	* generic/tclCompExpr.c (enum Marks): More stray trailing ","s

2008-02-26  Joe English  <[email protected]>

	* 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  <[email protected]>

	* generic/tclCompile.h: Remove stray trailing "," from enum
	InstOperandType definition (C99ism).

2008-02-26  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	*** 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  <[email protected]>

	* generic/tclExecute.c (INST_CONCAT1): Fix optimisation for in-place
	concatenation (was going over String type)

2008-02-02  Daniel Steffen  <[email protected]>

	* unix/configure.in (Darwin):	Correct Info.plist year substitution
					in non-framework builds.

	* unix/configure:		autoconf-2.59

2008-01-30  Miguel Sofer  <[email protected]>

	* generic/tclInterp.c (Tcl_GetAlias): Fix for [Bug 1882373], thanks go
	to an00na.

2008-01-30  Donal K. Fellows  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* changes:		Updated for 8.5.1 release.

2008-01-23  Don Porter  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* unix/README: Minor typo fixes [Bug 1853072]

	* generic/tclIO.c (TclGetsObjBinary): Operate on topmost channel.
	[Bug 1869405] (Ficicchia)

2008-01-17  Don Porter  <[email protected]>

	* generic/tclCompExpr.c:	Revision to preserve parsed intreps of
	numeric and boolean literals when compiling expressions with (optimize
	== 1).

2008-01-15  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* win/tclWinSerial.c (SerialCloseProc, TclWinOpenSerialChannel): Use
	critical section for read & write side. [Bug 1353846] (newman)

2008-01-11  Miguel Sofer  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* doc/vwait.n: Add a missing be to fix a typo.

2008-01-04  Jeff Hobbs  <[email protected]>

	* 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  <[email protected]>

	* 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  <[email protected]>

	* 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
# README:  Tcl

This is the **Tcl 9.0a2** source distribution.

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












[![Build Status](https://travis-ci.org/tcltk/tcl.svg?branch=master)](https://travis-ci.org/tcltk/tcl)



## Contents
 1. [Introduction](#intro)
 2. [Documentation](#doc)
 3. [Compiling and installing Tcl](#build)
 4. [Development tools](#devtools)
 5. [Tcl newsgroup](#complangtcl)


|




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







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

This is the **Tcl 9.0b2** source distribution.

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

8.6 (production release, daily build)
[![Build Status](https://github.com/tcltk/tcl/workflows/Linux/badge.svg?branch=core-8-6-branch)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22Linux%22+branch%3Acore-8-6-branch)
[![Build Status](https://github.com/tcltk/tcl/workflows/Windows/badge.svg?branch=core-8-6-branch)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22Windows%22+branch%3Acore-8-6-branch)
[![Build Status](https://github.com/tcltk/tcl/workflows/macOS/badge.svg?branch=core-8-6-branch)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22macOS%22+branch%3Acore-8-6-branch)
<br>
8.7 (in development, daily build))
[![Build Status](https://github.com/tcltk/tcl/workflows/Linux/badge.svg?branch=core-8-branch)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22Linux%22+branch%3Acore-8-branch)
[![Build Status](https://github.com/tcltk/tcl/workflows/Windows/badge.svg?branch=core-8-branch)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22Windows%22+branch%3Acore-8-branch)
[![Build Status](https://github.com/tcltk/tcl/workflows/macOS/badge.svg?branch=core-8-branch)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22macOS%22+branch%3Acore-8-branch)
<br>
9.0 (in development, daily build))
[![Build Status](https://github.com/tcltk/tcl/workflows/Linux/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22Linux%22+branch%3Amain)
[![Build Status](https://github.com/tcltk/tcl/workflows/Windows/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22Windows%22+branch%3Amain)
[![Build Status](https://github.com/tcltk/tcl/workflows/macOS/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions?query=workflow%3A%22macOS%22+branch%3Amain)

## 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
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/).
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
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.
The home page for this release, including new features, is
[here](https://www.tcl.tk/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







|





|





|

|







38
39
40
41
42
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 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
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
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 on our website.
The home page for this release, including new features, is
[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
## <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
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
more.  More information can be found at

	http://www.ActiveState.com/Tcl

## <a id="complangtcl">5.</a> Tcl newsgroup
There is a USENET news group, "`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.







|


|


|


|







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
## <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
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
more.  More information can be found at

	https://www.activestate.com/products/tcl/

## <a id="complangtcl">5.</a> Tcl newsgroup
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 <[email protected]>.
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
      [email protected]).
    - 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 [email protected]
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
<[email protected]> 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 ([email protected])

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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# Tcl/Tk 9.0b2 Release Announcement
April ??, 2024

The Tcl Core Team is pleased to announce the 9.0b2 releases of the Tcl
dynamic language and the Tk graphical interface package.  These are the
second beta releases of Tcl 9.0 and Tk 9.0.  More details can be found below.

We would like to express our gratitude to all those who submit bug
reports and patches.  This information is invaluable in enabling us
to identify and eliminate problems in the core. Such reports can be
submitted here.

        https://core.tcl-lang.org/tcl/ticket
        https://core.tcl-lang.org/tk/ticket

We ask that you log in (anonymous if you wish) to create tickets.
This deters abuse of the ticketing system.

## Contents
 1. [Where to get the new releases](#wheretoget)
 2. [General Summary](#summary)
 3. [Some of the most noteworthy changes](#changes)
 4. [Tcl Improvement Proposals (TIPs)](#tips)
 5. [Additional support resources](#support)
 6. [For additional information](#info)

## <a id="wheretoget">1.</a> Where to get the new releases

Tcl/Tk 9.0b2 sources are freely available as open source from the Tcl
SourceForge project's file distribution area:

        https://sourceforge.net/projects/tcl/files/

This distribution is source code only.  We keep links to some third
parties offering pre-built binaries for various systems here:

        https://www.tcl-lang.org/software/tcltk/bindist.html

## <a id="summary">2.</a> General Summary

These are new major versions of both Tcl and Tk.  There are new features
to be enjoyed.  There are incompatibilities to be considered. The list
of both is long and detailed and not fully included here.  We believe many
scripts written for Tcl 8 will run unchanged in Tcl 9.  We believe many more
can be modified in small and simple ways to produce a new script that runs
in both Tcl 8 and Tcl 9.  We expect that extensions and applications using
the public C APIs of Tcl and Tk will involve more effort, but that it is
still within reasonable reach to produce source code supporting both Tcl 8
and Tcl 9 while both releases remain in widespread use.

These are beta releases.  The developers believe the new feature set is
complete enough and the code quality is high enough that it is time for
a larger audience of Tcl/Tk users to give them a try and report back
to the developers what difficulties need resolution before stable
releases of Tcl/Tk 9.0.0.

The experiences of Tcl/Tk 8 users adapting their code to the beta releases
of Tcl/Tk 9 will shape the final interfaces of Tcl/Tk 9.0.0, and will
determine the need for possible Tcl/Tk 8.7 releases that might supply
additional lifecycle and migration support.

It is not recommended to deploy these beta releases directly to mission
critical use without significant testing and review.

## <a id="changes">3.</a> Some of the most noteworthy changes

Tcl 9:

  * 64-bit capacity: Data values larger than 2Gb

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

  * Unix notifiers available using epoll() or kqueue()
    - relieves limits on file descriptors imposed by legacy select()

  * Notable incompatibilities
    - Unqualified varnames resolved in current namespace, not global.
    - 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
    - Removed the "identity" encoding
    - $::tcl_precision no longer controls string generation of doubles
    - Removed Tcl 7 legacies: [case], [puts] [read] variant syntaxes
    - Removed subcommands [trace variable|vdelete|vinfo]
    - No -eofchar option for channels anymore for writing.
    - On Windows 10+ (Version 1903 or higher), system encoding is always utf-8.

  * Incompatibilities in C public interface
    - Many arguments expanded type from int to Tcl_Size
    - 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
    - Removed routines:
        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()

  * New commands
    - [array default], [array for]
    - [coroinject], [coroprobe]
    - [clock add weekdays]
    - [const], [info const*]
    - [dict getdefault]
    - [file tempdir], [file home], [file tildeexpand]
    - [info commandtype]
    - [ledit]
    - [lpop]
    - [lremove]
    - [lseq]
    - [package files]
    - [string insert], [string is dict]
    - [tcl::process]
    - [*::build-info]

  * New command options
    - [regsub ... -command ...]
    - [lsearch ... -stride ...]
    - [clock scan ... -validate ...]
    - [socket ... -nodelay ... -keepalive ...]
    - [vwait] controlled by several new options

  * Numbers
    - 0NNN format is no longer octal interpretation. Use 0oNNN.
    - 0dNNNN format to compel decimal interpretation.
    - NN_NNN_NNN, underscores in numbers for optional readability
    - Functions: isinf() isnan() isnormal() issubnormal() isunordered()
    - [fpclassify]
    - Function int() no longer truncates to word size

  * tcl::oo facilities
    - private variable and methods
    - [method -export], [method -unexport]

Tk 9:

  * Many improvements to use of platform features and conventions.
    - Built-in widgets and themes are scaling-aware.
    - Improved support of two-finger gestures, where available
    - The [tk windowingsystem] "aqua" needs macOS 10.10 or later

  * New commands and options
    - [tk sysnotify]: access to the OS notifications system
    - [tk systray]: access to the OS tray facility
    - [tk print]: access to the OS printing facility

  * Widget options
    - New ttk::progressbar option: -text
    - [$frame ... -backgroundimage $img -tile $bool]
    - [$menu id], [$menu add|insert ... ?$id? ...]
    - [$image get ... -withalpha ...]
    - All indices now accept the forms "end", "end-int", "int+|-int"

  * Improved widget appearance
    - ttk::notebook with nondefault tab positions

  * Images
    - Partial SVG support
    - Read/write access to photo image metadata

## <a id="tips">4.</a> Tcl Improvement Proposals (TIPs)

Each new user-visible feature in Tcl or Tk should find its origins in
a Tcl Improvement Proposal (TIP).  TIPs are published, edited, considered
and voted in public, and should contain valuable information about how
a feature came to be the way it is.  See the full collection here:

    https://tip.tcl-lang.org/

## <a id="support">5.</a> Additional support resources

See the following links for an accumulation of migration advice:

https://core.tcl-lang.org/tcl/wiki?name=Migrating+C+extensions+to+Tcl+9
https://core.tcl-lang.org/tcl/wiki?name=Migrating+scripts+to+Tcl+9

There has been much progress already porting many known applications,
extensions, and packages in the Tcl world to compatibility with Tcl/Tk 9:

https://wiki.tcl-lang.org/page/Apps+confirmed+to+work+with+Tcl+9
https://wiki.tcl-lang.org/page/Porting+extensions+to+Tcl+9

## <a id="info">6.</a> For additional information:

Please visit the Tcl Developer Xchange web site:

        https://www.tcl-lang.org/

This site contains a variety of information about Tcl/Tk in general, the
core Tcl and Tk distributions, Tcl development tools, and much more.

--
Tcl Core Team and Maintainers
Don Porter, Tcl Core Release Manager

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










































































































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/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
    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->pid = result;
	waitPtr->status = status;
	waitPtr->nextPtr = deadList;
	deadList = waitPtr;

    waitAgain:
	continue;







|
>
>
>
>







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_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
cmake_minimum_required(VERSION 2.4.4)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

project(zlib C)

set(VERSION "1.2.11")

option(ASM686 "Enable building i686 assembly implementation")
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")

|




|

|
<







1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
cmake_minimum_required(VERSION 2.4.4...3.15.0)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

project(zlib C)

set(VERSION "1.3.1")

option(ZLIB_BUILD_EXAMPLES "Enable Zlib Examples" ON)


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

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.







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







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


































# 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
                            -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})

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








|
>
|
>

















|







145
146
147
148
149
150
151
152
153
154
155
156
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_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 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

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)

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)

    add_executable(minigzip64 test/minigzip.c)
    target_link_libraries(minigzip64 zlib)
    set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
endif()








|
|
|
|

|
|

|
|
|
|
|

|
|
|
|
>
193
194
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
#============================================================================
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)

    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()
endif()

Changes to compat/zlib/ChangeLog.

1
2
3







































































































4
5
6
7
8
9
10

                ChangeLog file for zlib








































































































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



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







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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
- 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
- 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







|







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







|






|







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







|







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







|







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







|







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

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.

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]







|







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

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







|







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

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)







|




|

|







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

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







|







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
- 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
 . 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)
- 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".
- 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







|













|







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)
- 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"
- 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
- 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.
- 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.
- 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 <[email protected]>
        386 asm code replacing longest_match().
   contrib/iostream/ by Kevin Ruland <[email protected]>
        A C++ I/O streams interface to the zlib gz* functions
   contrib/iostream2/  by Tyge Løvset <[email protected]>
        Another C++ I/O streams interface
   contrib/untgz/  by "Pedro A. Aranda Guti\irrez" <[email protected]>
        A very simple tar.gz file extractor using zlib
   contrib/visual-basic.txt by Carlos Rios <[email protected]>
        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.
- 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).
- 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.
- 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.
- 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







|
|



|











|







|








|
|












|









|




















|







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
- 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
- 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 <[email protected]>
        386 asm code replacing longest_match()
   contrib/iostream/ by Kevin Ruland <[email protected]>
        A C++ I/O streams interface to the zlib gz* functions
   contrib/iostream2/  by Tyge Løvset <[email protected]>
        Another C++ I/O streams interface
   contrib/untgz/  by "Pedro A. Aranda Guti\irrez" <[email protected]>
        A very simple tar.gz file extractor using zlib
   contrib/visual-basic.txt by Carlos Rios <[email protected]>
        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
- 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)
- 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
- 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
- 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
- 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.
- 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.
- 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







|




















|







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
- 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
- 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
- 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 Z_BINARY instead of BINARY
- document that gzclose after gzdopen will close the file
- 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).
- 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.
- 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?).
- 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).
- default window size is same for compression and decompression
  (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).

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

Changes in 0.7 (14 April 95)
- 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.

Changes in 0.61 (12 April 95)
- 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.
- fixed bug in gzread (don't read crc as data)
- 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.
- support decompression but only in a single step (forced Z_FINISH)
- 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.

Changes in 0.4:
- avoid "zip" everywhere, use zlib instead of ziplib.
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
  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 inflateInit2
- simplied considerably deflateInit and inflateInit by not supporting
  user-provided history buffer. This is supported only in deflateInit2
  and inflateInit2.

Changes in 0.3:
- prefix all macro names with Z_
- use Z_FINISH instead of deflateEnd to finish compression.
- added Z_HUFFMAN_ONLY
- added gzerror()







|


|





|


|


|






|

|

|








|




|


















|

















|








|









|


|


|


|




|

|





|

|

|
|
|


|

|


|

|

|



|


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 Z_BINARY instead of BINARY
- document that gzclose after gzdopen will close the file
- 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)
- 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
- 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?)
- 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)
- default window size is same for compression and decompression
  (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)

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

Changes in 0.7 (14 April 95)
- 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

Changes in 0.61 (12 April 95)
- 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
- fixed bug in gzread (don't read crc as data)
- 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
- support decompression but only in a single step (forced Z_FINISH)
- 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

Changes in 0.4:
- avoid "zip" everywhere, use zlib instead of ziplib
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
  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 inflateInit2
- simplified considerably deflateInit and inflateInit by not supporting
  user-provided history buffer. This is supported only in deflateInit2
  and inflateInit2

Changes in 0.3:
- prefix all macro names with Z_
- 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

                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


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







|









|
<







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


 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
  [email protected]          [email protected]

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
# Makefile for zlib
# Copyright (C) 1995-2017 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
LDSHARED=$(CC)
CPP=$(CC) -E

STATICLIB=libz.a
SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.11
SHAREDLIBM=libz.so.1
LIBS=$(STATICLIB) $(SHAREDLIBV)

AR=ar
ARFLAGS=rc
RANLIB=ranlib
LDCONFIG=ldconfig

|







<
<
<
<















|





|







1
2
3
4
5
6
7
8
9




10
11
12
13
14
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-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 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_LIBS=-L. libz.a
LDSHARED=$(CC)
CPP=$(CC) -E

STATICLIB=libz.a
SHAREDLIB=libz.so
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

check: test

test: all teststatic testshared

teststatic: static
	@TMPST=tmpst_$$; \
	if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \
	  echo '		*** zlib test OK ***'; \
	else \
	  echo '		*** zlib test FAILED ***'; false; \
	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 \
	  echo '		*** zlib shared test OK ***'; \
	else \
	  echo '		*** zlib shared test FAILED ***'; false; \
	fi; \
	rm -f $$TMPSH

test64: all64
	@TMP64=tmp64_$$; \
	if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \
	  echo '		*** zlib 64-bit test OK ***'; \
	else \
	  echo '		*** zlib 64-bit test FAILED ***'; false; \
	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
	gcov inf*.c

libz.a: $(OBJS)
	$(AR) $(ARFLAGS) $@ $(OBJS)
	-@ ($(RANLIB) $@ || true) >/dev/null 2>&1

match.o: match.S







|



|
|







|



|
|



|



|
|









|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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 | ${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_$$

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 | ${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_$$

test64: all64
	@TMP64=tmp64_$$; \
	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_$$

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
	${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
	$(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)

minigzip$(EXE): minigzip.o $(STATICLIB)
	$(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS)

examplesh$(EXE): example.o $(SHAREDLIBV)
	$(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV)

minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
	$(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV)

example64$(EXE): example64.o $(STATICLIB)
	$(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS)

minigzip64$(EXE): minigzip64.o $(STATICLIB)
	$(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS)

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







|


|


|


|


|


|







278
279
280
281
282
283
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) $(LDFLAGS) -o $@ example.o $(TEST_LIBS)

minigzip$(EXE): minigzip.o $(STATICLIB)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ minigzip.o $(TEST_LIBS)

examplesh$(EXE): example.o $(SHAREDLIBV)
	$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) -L. $(SHAREDLIBV)

minigzipsh$(EXE): minigzip.o $(SHAREDLIBV)
	$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) -L. $(SHAREDLIBV)

example64$(EXE): example64.o $(STATICLIB)
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ example64.o $(TEST_LIBS)

minigzip64$(EXE): minigzip64.o $(STATICLIB)
	$(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
	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







mostlyclean: clean
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
	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







>
>
>
>
>
>

|











|






<
<







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



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
ZLIB DATA COMPRESSION LIBRARY

zlib 1.2.11 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 [email protected]).  A usage example


|







1
2
3
4
5
6
7
8
9
10
ZLIB DATA COMPRESSION LIBRARY

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 [email protected]).  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
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 <[email protected]> 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/ .

The changes made in version 1.2.11 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/ .

A Perl interface to zlib written by Paul Marquess <[email protected]> is available
at CPAN (Comprehensive Perl Archive Network) sites, including
http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .

A Python interface to zlib written by A.M. Kuchling <[email protected]> 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 .








|

|



|
|

|
<
|







25
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 <[email protected]> wrote an article about zlib for the Jan.  1997
issue of Dr.  Dobb's Journal; a copy of the article is available at
https://marknelson.us/posts/1997/01/01/zlib-engine.html .

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. Follow the API
Documentation link at: https://docs.oracle.com/search/?q=java.util.zip .

A Perl interface to zlib and bzip2 written by Paul Marquess <[email protected]>

can be found at https://github.com/pmqs/IO-Compress .

A Python interface to zlib written by A.M. Kuchling <[email protected]> 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
- 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
  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

  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







|



















|







59
60
61
62
63
64
65
66
67
68
69
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 (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-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

  Jean-loup Gailly        Mark Adler
  [email protected]          [email protected]

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.




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.







|
>
>
>




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

  Jean-loup Gailly        Mark Adler
  [email protected]          [email protected]

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.  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
/* 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);









<
<







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"



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








|
<
<
<
<







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

    /* return recombined sums */
    return adler | (sum2 << 16);
}

/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
    uLong adler;
    const Bytef *buf;
    uInt len;
{
    return adler32_z(adler, buf, len);
}

/* ========================================================================= */
local uLong adler32_combine_(adler1, adler2, 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;







|
<
<
<
<




|
<
<
<
<







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(uLong adler, const Bytef *buf, uInt len) {




    return adler32_z(adler, buf, len);
}

/* ========================================================================= */
local uLong adler32_combine_(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
    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 adler1;
    uLong adler2;
    z_off_t len2;
{
    return adler32_combine_(adler1, adler2, len2);
}

uLong ZEXPORT adler32_combine64(adler1, adler2, len2)
    uLong adler1;
    uLong adler2;
    z_off64_t len2;
{
    return adler32_combine_(adler1, adler2, len2);
}







|
<
<
<
<



|
<
<
<
<


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(uLong adler1, uLong adler2, z_off_t len2) {




    return adler32_combine_(adler1, adler2, len2);
}

uLong ZEXPORT adler32_combine64(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
   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 level;
{
    z_stream stream;
    int err;
    const uInt max = (uInt)-1;
    uLong left;

    left = *destLen;
    *destLen = 0;







<
<
<
|
|
<
<







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(Bytef *dest, uLongf *destLen, const Bytef *source,
                      uLong sourceLen, 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
    *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;
{
    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 sourceLen;
{
    return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
           (sourceLen >> 25) + 13;
}







<
<
<
|
|
<







|
<
<



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(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(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
# get source directory
SRCDIR=`dirname $0`
if test $SRCDIR = "."; then
    ZINC=""
    ZINCOUT="-I."
    SRCDIR=""
else
    ZINC='-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/'`"

    CROSS_PREFIX="${CHOST}-"


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

# 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"}







|






|
>

>
>







|
<
|







21
22
23
24
25
26
27
28
29
30
31
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='-I. -include zconf.h'
    ZINCOUT='-I. -I$(SRCDIR)'
    SRCDIR="$SRCDIR/"
fi

# set command prefix for cross-compilation
if [ -n "${CHOST}" ]; then
    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=`echo ${VER}|sed -n -e 's/\([0-9]\{1,\}\(\\.[0-9]\{1,\}\)\{1,2\}\).*/\1/p'`

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
cover=0
zprefix=0
zconst=0
build64=0
gcc=0
warn=0
debug=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
  echo -------------------- >> configure.log
  echo >> configure.log
  echo >> configure.log
  exit $1
}

# process command line options







>
>











|







85
86
87
88
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 -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
    -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 ;;



    *)
      echo "unknown option: $1" | tee -a configure.log
      echo "$0 --help for help" | tee -a configure.log
      leave 1;;
    esac
done








>
>
>







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

# 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


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
case "$cc" in
  *gcc*) gcc=1 ;;
  *clang*) gcc=1 ;;
esac
case `$cc -v 2>&1` in
  *gcc*) gcc=1 ;;
  *clang*) gcc=1 ;;







>
|
>
|
>
>
>
>
|
>
|







168
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
  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
  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"
    else
      CFLAGS="${CFLAGS} -Wall -Wextra -pedantic"
    fi
  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*)




        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*)
        EXE='.exe' ;;
  MINGW* | mingw*)
# temporary bypass
        rm -f $test.[co] $test $test$shared_ext
        echo "Please use win32/Makefile.gcc instead." | 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
         # ([email protected])
                 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"} ;;
  esac
else
  # find system name and corresponding cc options
  CC=${CC-cc}
  gcc=0
  echo ... using $CC >> configure.log
  if test -z "$uname"; then







|

|


>
>
>
>
>
>








|
>
>
>
>




|

|
<

|
<



|
|
|

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







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241

242
243

244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
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 -DZLIB_CONST"
    else
      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* | *-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* | *-cygwin* | OS/2*)
        EXE='.exe' ;;
  MINGW* | mingw* | *-mingw*)

        rm -f $test.[co] $test $test$shared_ext
        echo "If this doesn't work for you, try win32/Makefile.gcc." | tee -a configure.log

        LDSHARED=${LDSHARED-"$cc -shared"}
        LDSHAREDLIBC=""
        EXE='.exe' ;;
  QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
        # ([email protected])
        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 ;;
  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
    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
    ret=$?



    if test $ret -ne 0; then
      echo "(exit code "$ret")" >> configure.log
    fi
    return $ret
  }
fi

tryboth()
{
  show $*
  got=`( $* ) 2>&1`
  ret=$?

  printf %s "$got" >> configure.log

  if test $ret -ne 0; then

    return $ret
  fi
  test "$got" = ""
}

cat > $test.c << EOF
int foo() { return 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
    test "`( $* ) 2>&1 | tee -a configure.log`" = ""
  }
  echo - using any output from compiler to indicate an error >> configure.log
else
  try()
  {
    show $*
    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\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
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 &&
     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







|







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

echo >> configure.log

# find the size_t integer type, if needed
if test $need_sizet -eq 1; then
  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) {







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










<


<
<
|
<
|
<
<
|







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















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

else
  echo "Checking for size_t... No." | tee -a configure.log


  # find a size_t integer type

  # check for long long


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


  else
    echo "Failed to find a pointer-size integer type." | 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>







>
>

|
<

<
<
<
<
<







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 "Checking for a pointer-size integer type... not found." | tee -a configure.log

  fi





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
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
sed < ${SRCDIR}Makefile.in "
/^CC *=/s#=.*#=$CC#
/^CFLAGS *=/s#=.*#=$CFLAGS#
/^SFLAGS *=/s#=.*#=$SFLAGS#
/^LDFLAGS *=/s#=.*#=$LDFLAGS#
/^LDSHARED *=/s#=.*#=$LDSHARED#
/^CPP *=/s#=.*#=$CPP#







<









|







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

# 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
All files under this contrib directory are UNSUPPORTED. There 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 <[email protected]>
        Support for Ada
        See http://zlib-ada.sourceforge.net/

amd64/      by Mikhail Teterin <[email protected]>
        asm code for AMD64
        See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393

asm686/     by Brian Raiter <[email protected]>
        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 <[email protected]>
        Decompressor for output of PKWare Data Compression Library (DCL)

delphi/     by Cosmin Truta <[email protected]>
        Support for Delphi and C++ Builder

dotzlib/    by Henrik Ravn <[email protected]>
        Support for Microsoft .Net and Visual C++ .Net

gcc_gvmat64/by Gilles Vollant <[email protected]>
        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 <[email protected]>
        Unsupported diffs to infback to decode the deflate64 format

inflate86/  by Chris Anderson <[email protected]>
        Tuned x86 gcc asm code to replace inflate_fast()

iostream/   by Kevin Ruland <[email protected]>
        A C++ I/O streams interface to the zlib gz* functions

iostream2/  by Tyge Løvset <[email protected]>
        Another C++ I/O streams interface

iostream3/  by Ludwig Schwardt <[email protected]>
            and Kevin Ruland <[email protected]>
        Yet another C++ I/O streams interface

masmx64/    by Gilles Vollant <[email protected]>
        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 <[email protected]>
        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 <[email protected]>
        Mini zip and unzip based on zlib
        Includes Zip64 support by Mathias Svensson <[email protected]>
        See http://www.winimage.com/zLibDll/minizip.html

pascal/     by Bob Dellaca <[email protected]> et al.
        Support for Pascal
|









<
<
<
<
<
<
<
<
















<
<
<










<
<
<
<
<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10








11
12
13
14
15
16
17
18
19
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. 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 <[email protected]>
        Support for Ada
        See http://zlib-ada.sourceforge.net/









blast/      by Mark Adler <[email protected]>
        Decompressor for output of PKWare Data Compression Library (DCL)

delphi/     by Cosmin Truta <[email protected]>
        Support for Delphi and C++ Builder

dotzlib/    by Henrik Ravn <[email protected]>
        Support for Microsoft .Net and Visual C++ .Net

gcc_gvmat64/by Gilles Vollant <[email protected]>
        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 <[email protected]>
        Unsupported diffs to infback to decode the deflate64 format




iostream/   by Kevin Ruland <[email protected]>
        A C++ I/O streams interface to the zlib gz* functions

iostream2/  by Tyge Løvset <[email protected]>
        Another C++ I/O streams interface

iostream3/  by Ludwig Schwardt <[email protected]>
            and Kevin Ruland <[email protected]>
        Yet another C++ I/O streams interface











minizip/    by Gilles Vollant <[email protected]>
        Mini zip and unzip based on zlib
        Includes Zip64 support by Mathias Svensson <[email protected]>
        See http://www.winimage.com/zLibDll/minizip.html

pascal/     by Bob Dellaca <[email protected]> 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
                        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,
  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.











|
|







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:

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







|




|







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








|







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







|







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

   Filtered         : constant Strategy_Type;
   Huffman_Only     : constant Strategy_Type;
   RLE              : constant Strategy_Type;
   Default_Strategy : constant Strategy_Type;

   Default_Buffer_Size : constant := 4096;







|







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 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
[email protected]
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
[email protected]
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
 * 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.
 *
 * 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.
 *







|







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

type
  EZlibError = class(Exception);
  ECompressionError = class(EZlibError);
  EDecompressionError = class(EZlibError);

implementation







|







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.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
//
// 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;

|







1
2
3
4
5
6
7
8
9
//
// © 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
        /// </summary>
        public ChecksumGeneratorBase()
        {
            _current = 0;
        }

        /// <summary>
        /// Initializes a new instance of the checksum generator basewith a specified value
        /// </summary>
        /// <param name="initialValue">The value to set the current checksum to</param>
        public ChecksumGeneratorBase(uint initialValue)
        {
            _current = initialValue;
        }








|







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







|







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

|







1
2
3
4
5
6
7
8
9
//
// © 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
//
// 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;

|







1
2
3
4
5
6
7
8
9
//
// © 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

        /// <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()
        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
        /// </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);







|




















|







135
136
137
138
139
140
141
142
143
144
145
146
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 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 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
//
// 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;

|







1
2
3
4
5
6
7
8
9
//
// © 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
//
// 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;

|







1
2
3
4
5
6
7
8
9
//
// © 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
//
// 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;

|







1
2
3
4
5
6
7
8
9
//
// © 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
        /// <exception cref="NotSupportedException">Always thrown</exception>
        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        ///  Not suppported.
        /// </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)
        {







|







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 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
        /// 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.
        /// </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.
        /// </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
    }
}







|
















|













264
265
266
267
268
269
270
271
272
273
274
275
276
277
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 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 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
//
// 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;

|







1
2
3
4
5
6
7
8
9
//
// © 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
    public class InfoTests
    {
        #region Info tests
        [Test]
        public void Info_Version()
        {
            Info info = new Info();
            Assert.AreEqual("1.2.11", Info.Version);
            Assert.AreEqual(32, info.SizeOfUInt);
            Assert.AreEqual(32, info.SizeOfULong);
            Assert.AreEqual(32, info.SizeOfPointer);
            Assert.AreEqual(32, info.SizeOfOffset);
        }
        #endregion
    }







|







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







|







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

/*
   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 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;







<
<
|
|
<
<







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_(z_stream FAR *strm, unsigned char FAR *window,
                              const char *version, 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
/*
   Build and output length and distance decoding tables for fixed code
   decoding.
 */
#ifdef MAKEFIXED
#include <stdio.h>

void makefixed9(void)
{
    unsigned sym, bits, low, size;
    code *next, *lenfix, *distfix;
    struct inflate_state state;
    code fixed[544];

    /* literal/length table */
    sym = 0;







|
<







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

    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
   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;
in_func in;
void FAR *in_desc;
out_func out;
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 */







<
|
<
<
|
<
<







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(z_stream FAR *strm, in_func in, void FAR *in_desc,


                         out_func out, 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
    /* Return unused input */
  inf_leave:
    strm->next_in = next;
    strm->avail_in = have;
    return ret;
}

int ZEXPORT inflateBack9End(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;
}







|
<
<







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(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
 * 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));
#define inflateBack9Init(strm, window) \
        inflateBack9Init_((strm), (window), \
        ZLIB_VERSION, sizeof(z_stream))

#ifdef __cplusplus
}
#endif







|
|
|
|
|
|
|
|







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(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
/* inftree9.c -- generate Huffman trees for efficient decoding
 * Copyright (C) 1995-2017 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 ";
/*
  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;
unsigned codes;
code FAR * FAR *table;
unsigned FAR *bits;
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 */

|









|



















<
<
|
<
|
<
|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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-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.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(codetype type, unsigned short FAR *lens, unsigned codes,

                   code FAR * FAR *table, unsigned FAR *bits,

                   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
    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};
    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,







|







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, 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
    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
   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
   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));







|


|
|













|
|
|
34
35
36
37
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 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 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(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 <[email protected]>
 * 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
 *  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
    template <typename Ta, typename Tb>
      friend gzofstream&
      operator<<(gzofstream&,
                 const gzomanip2<Ta,Tb>&);

    // Constructor
    gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2),







|







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







|











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

// 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 <[email protected]>
 * 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 <[email protected]>
; * 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 <[email protected]>
;;; 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
CC=cc
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


	./minizip test readme.txt
	./miniunz -l test.zip
	mv readme.txt readme.old
	./miniunz test.zip



clean:
	/bin/rm -f *.o *~ minizip miniunz
|
|
















>
>
|

|

>
>


|
1
2
3
4
5
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 := $(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 test.txt
	./miniunz -l test.zip
	@mv test.txt test.old
	./miniunz test.zip
	@cmp test.txt test.old
	@rm -f test.*

clean:
	/bin/rm -f *.o *~ minizip miniunz test.*

Changes to compat/zlib/contrib/minizip/MiniZip64_Changes.txt.

1
2
3
4
5
6

MiniZip 1.1 was derrived from MiniZip at version 1.01f

Change in 1.0 (Okt 2009)
 - **TODO - Add history**


|




1
2
3
4
5
6

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
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_INIT([minizip], [1.2.11], [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])



|







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.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
*/

#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)
{
    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;


    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)
{
    (*(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)
{
    *(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))

#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 */
#  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)
{
    int 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;







|
<



<

>







|
<















|
<













|






|


|
|
|
|
|
|
<
|







28
29
30
31
32
33
34
35

36
37
38

39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72
73
74
75
76
77
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) {

    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;
    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) {

    (*(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) {

    *(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), (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 */
#  endif

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

    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
        #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)
// 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)
{
    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)
{
    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)
{
    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);
        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)
{
    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)
{
    FILE* file = NULL;
    const char* mode_fopen = NULL;

    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)
{
    FILE* file = NULL;
    const char* mode_fopen = NULL;

    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)
{
    uLong ret;

    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)
{
    uLong ret;

    ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
    return ret;
}

static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
{
    long ret;

    ret = ftell((FILE *)stream);
    return ret;
}


static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
{
    ZPOS64_T ret;

    ret = FTELLO_FUNC((FILE *)stream);
    return ret;
}

static long ZCALLBACK fseek_file_func (voidpf  opaque, voidpf stream, uLong offset, int origin)
{
    int fseek_origin=0;
    long ret;

    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)
        ret = -1;
    return ret;
}

static long ZCALLBACK fseek64_file_func (voidpf  opaque, voidpf stream, ZPOS64_T offset, int origin)
{
    int fseek_origin=0;
    long ret;

    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)
                        ret = -1;

    return ret;
}


static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
{
    int ret;

    ret = fclose((FILE *)stream);
    return ret;
}

static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
{
    int ret;

    ret = ferror((FILE *)stream);
    return ret;
}

void fill_fopen_filefunc (pzlib_filefunc_def)
  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)
{
    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;
}







|













|
<








|
<












|
<




|







|
<


<













<
<
<
<
<
<
<
<
|
<


>














|
<


>















|
<

>




|
<

>




|
<

>





|
<

>
|



|
<


>














|




|
<


>















|






|
<

>




|
<

>




<
|
<










|
<









14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70

71
72

73
74
75
76
77
78
79
80
81
82
83
84
85








86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

124
125
126
127
128
129
130

131
132
133
134
135
136
137

138
139
140
141
142
143
144
145

146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208

209
210
211
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) || 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) {

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

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

    if (pfilefunc->zfile_func64.zseek64_file != NULL)
        return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
    else
    {
        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) {

    p_filefunc64_32->zfile_func64.zopen64_file = NULL;
    p_filefunc64_32->zopen32_file = p_filefunc32->zopen_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(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) {

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

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

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

    long ret;
    (void)opaque;
    ret = ftell((FILE *)stream);
    return ret;
}


static ZPOS64_T ZCALLBACK ftell64_file_func(voidpf opaque, voidpf stream) {

    ZPOS64_T ret;
    (void)opaque;
    ret = (ZPOS64_T)FTELLO_FUNC((FILE *)stream);
    return ret;
}

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, (long)offset, fseek_origin) != 0)
        ret = -1;
    return ret;
}

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, (z_off64_t)offset, fseek_origin) != 0)
                        ret = -1;

    return ret;
}


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

    int ret;
    (void)opaque;
    ret = ferror((FILE *)stream);
    return ret;
}


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

    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
#include "zlib.h"

#if defined(USE_FILE32API)
#define fopen64 fopen
#define ftello64 ftell
#define fseeko64 fseek
#else
#ifdef __FreeBSD__
#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)))







|







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
#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
#endif
*/

#ifdef HAVE_MINIZIP64_CONF_H
#include "mz64conf.h"
#endif

/* a type choosen 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






#ifdef __cplusplus
extern "C" {
#endif


#define ZLIB_FILEFUNC_SEEK_CUR (1)







|








|
<









|
>
>
>







78
79
80
81
82
83
84
85
86
87
88
89
90
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 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




#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
   #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 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));


/* here is the "old" 32 bits structure 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 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));

/* 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));

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







|
|
|
|
|

|
|


|












|
|
|













|
|


















|
|
|

|










130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
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)      (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)      (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 */
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)    (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(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(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);

#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
#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 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)
{
    *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)
{
    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)
{
    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







>
>
>
>
>





<
<
<
<
<
<
<
<











|
<




















|
<

















|
<







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40








41
42
43
44
45
46
47
48
49
50
51
52

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

74
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









typedef struct
{
    HANDLE hf;
    int error;
} WIN32FILE_IOWIN;


static void win32_translate_open_mode(int mode,
                                      DWORD* lpdwDesiredAccess,
                                      DWORD* lpdwCreationDisposition,
                                      DWORD* lpdwShareMode,
                                      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) {

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

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







|
<







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

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







|
<


















|
<







135
136
137
138
139
140
141
142

143
144
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) {

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

    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
        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 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 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)
{
#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 ret=-1;
    HANDLE hFile = NULL;
    if (stream!=NULL)
        hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
    if (hFile != NULL)
    {
        LARGE_INTEGER pos;







|
<




















|
<



















|
<


















|
<







182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230

231
232
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 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 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) {

#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 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
        }
        else
            ret=(long)pos.LowPart;
    }
    return ret;
}

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







|
<







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 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
        else
            ret=pos.QuadPart;
    }
    return ret;
}


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)







|
<







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

    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
        }
        else
            ret=0;
    }
    return ret;
}

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;








|
<







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

    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
        }
        else
            ret=0;
    }
    return ret;
}

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 ret=-1;
    if (stream!=NULL)
    {
        ret = ((WIN32FILE_IOWIN*)stream) -> error;
    }
    return ret;
}

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)
{
    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)
{
    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)
{
    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;
}







|
<
















|
<








|
<










|
<











|
<











|
<









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 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 ret=-1;
    if (stream!=NULL)
    {
        ret = ((WIN32FILE_IOWIN*)stream) -> error;
    }
    return ret;
}

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

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

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

    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
#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));

#ifdef __cplusplus
}
#endif







|
|
|
|




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(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
                #define _LARGEFILE64_SOURCE
        #endif
        #ifndef _FILE_OFFSET_BIT
                #define _FILE_OFFSET_BIT 64
        #endif
#endif

#ifdef __APPLE__
// 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>


#ifdef _WIN32
# include <direct.h>
# include <io.h>
#else
# include <unistd.h>
# include <utime.h>







|

















>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
                #define _LARGEFILE64_SOURCE
        #endif
        #ifndef _FILE_OFFSET_BIT
                #define _FILE_OFFSET_BIT 64
        #endif
#endif

#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
  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)
    tmu_date : the SAME new date at the tm_unz format */
void change_file_date(filename,dosdate,tmu_date)
    const char *filename;
    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__)

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




#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;
{
    int ret=0;
#ifdef _WIN32
    ret = _mkdir(dirname);
#elif unix
    ret = mkdir (dirname,0775);
#elif __APPLE__
    ret = mkdir (dirname,0775);


#endif
    return ret;
}

int makedir (newdir)
    char *newdir;
{
  char *buffer ;
  char *p;
  int  len = (int)strlen(newdir);

  if (len <= 0)
    return 0;

  buffer = (char*)malloc(len+1);
        if (buffer==NULL)
        {
                printf("Error allocating memory\n");
                return UNZ_INTERNALERROR;







|

<
|
<
<
<













>















>
>
>
>








<
|
<







>
>




<
|
<


|

|







75
76
77
78
79
80
81
82
83

84



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

126

127
128
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)
    tmu_date : the SAME new date at the tm_unz format */

static void change_file_date(const char *filename, 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 */


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


static int makedir(const char *newdir) {

  char *buffer ;
  char *p;
  size_t len = strlen(newdir);

  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
        break;
      *p++ = hold;
    }
  free(buffer);
  return 1;
}

void do_banner()
{
    printf("MiniUnz 1.01b, 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()
{
    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");
}

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');







|
<
|



|
<







|


|
<







181
182
183
184
185
186
187
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;
}

static void do_banner(void) {

    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");
}

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 encrypted file using password\n\n");
}

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
          printf(" ");
      }
  }

  printf("%s",&number[pos_string]);
}

int do_list(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;
        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 */
        if ((file_info.flag & 1) != 0)
            charCrypt='*';

        if (file_info.compression_method==0)
            string_method="Stored";
        else
        if (file_info.compression_method==Z_DEFLATED)







|
<
<














|










|







224
225
226
227
228
229
230
231


232
233
234
235
236
237
238
239
240
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]);
}

static int do_list(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 = "";
        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 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
        }
    }

    return 0;
}


int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
    unzFile uf;
    const int* popt_extract_without_path;
    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;
    }







<
<
|
<
<
<









<







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




static int do_extract_currentfile(unzFile uf, const int* popt_extract_without_path, 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;

    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
        const char* write_filename;
        int skip=0;

        if ((*popt_extract_without_path)==0)
            write_filename = filename_inzip;
        else
            write_filename = filename_withoutpath;















        err = unzOpenCurrentFilePassword(uf,password);
        if (err!=UNZ_OK)
        {
            printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
        }








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







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
                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)
                    {
                        printf("error in writing extracted file\n");
                        err=UNZ_ERRNO;
                        break;
                    }
            }
            while (err>0);







|







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,(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
    }

    free(buf);
    return err;
}


int do_extract(uf,opt_extract_without_path,opt_overwrite,password)
    unzFile uf;
    int opt_extract_without_path;
    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++)
    {







<
<
|
<
<
<



<







471
472
473
474
475
476
477


478



479
480
481

482
483
484
485
486
487
488
    }

    free(buf);
    return err;
}




static int do_extract(unzFile uf, int opt_extract_without_path, int opt_overwrite, const char* password) {



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

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

    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;
    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[];
{
    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;







<
<
<
|
<
<
<
<















<
<
|
<







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




static int do_extract_onefile(unzFile uf, const char* filename, int opt_extract_without_path, int opt_overwrite, const char* password) {




    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(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
        {
            if ((*argv[i])=='-')
            {
                const char *p=argv[i]+1;

                while ((*p)!='\0')
                {
                    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'))







|







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++);
                    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
    {

#        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. */
        filename_try[ MAXFILENAME ] = '\0';

#        ifdef USEWIN32IOAPI
        fill_win32_filefunc64A(&ffunc);
        uf = unzOpen2_64(zipfilename,&ffunc);
#        else
        uf = unzOpen64(zipfilename);







|







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













>







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

#include "zip.h"

#ifdef _WIN32
        #define USEWIN32IOAPI
        #include "iowin32.h"



#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 */
{
  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 */
{

  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);
    if (len > MAXFILENAME)
      len = MAXFILENAME;

    strncpy(name, f,MAXFILENAME-1);
    /* strncpy doesnt 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)
    {







>
>
>








<
|
|
|
<



















<
|
|
|
<
>








|




|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

80
81
82

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

102
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

/* 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__)

/* 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];
    size_t len = strlen(f);
    if (len > MAXFILENAME)
      len = MAXFILENAME;

    strncpy(name, f,MAXFILENAME-1);
    /* 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
  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 */
{



    return 0;
}
#endif
#endif




int check_exist_file(filename)
    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()
{
    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()
{
    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)
{
   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;
   if (fin==NULL)
   {
       err = ZIP_ERRNO;
   }

    if (err == ZIP_OK)
        do
        {
            err = ZIP_OK;
            size_read = (int)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;

        } 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)
{
  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);

                printf("File : %s is %lld bytes\n", filename, pos);

    if(pos >= 0xffffffff)
     largeFile = 1;

                fclose(pFile);
  }








<
|
|
|
<
>
>
>








<
|
<










|
<




|
<












|
<





|









|








|
|











|
<






|
|

|







136
137
138
139
140
141
142

143
144
145

146
147
148
149
150
151
152
153
154
155
156

157

158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173

174
175
176
177
178
179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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

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





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

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");
}

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 */
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; */
   if (fin==NULL)
   {
       err = ZIP_ERRNO;
   }

    if (err == ZIP_OK)
        do
        {
            err = ZIP_OK;
            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_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;
}

static int isLargeFile(const char* filename) {

  int largeFile = 0;
  ZPOS64_T pos = 0;
  FILE* pFile = FOPEN_FUNC(filename, "rb");

  if(pFile != NULL)
  {
    FSEEKO_FUNC(pFile, 0, SEEK_END);
    pos = (ZPOS64_T)FTELLO_FUNC(pFile);

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


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

    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);
        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 i;
    int opt_recursive=0;
    int opt_overwrite=1;
    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;
    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++);;
                    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++;
                    }
                }
            }







|









|












<
<
|
<


|






|




















|










>







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[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;
        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(int argc, char *argv[]) {

    int i;
    int opt_recursive=0;
    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;
    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++);
                    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
    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. */
        filename_try[ MAXFILENAME ] = '\0';

        len=(int)strlen(filename_try);
        for (i=0;i<len;i++)
            if (filename_try[i]=='.')
                dot_found=1;








|







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







|
<
<
<
<
<
<







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(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
/*
Copyright (c) 2013-2017, tinydir authors:
- Cong Xu
- Lautis Sun
- Baudouin Feildel
- Andargor <[email protected]>
All rights reserved.

Redistribution and use in source and binary forms, with or without

|







1
2
3
4
5
6
7
8
9
/*
Copyright (c) 2013-2021, tinydir authors:
- Cong Xu
- Lautis Sun
- Baudouin Feildel
- Andargor <[email protected]>
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
#define _UNICODE
#endif

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER

# define WIN32_LEAN_AND_MEAN

# include <windows.h>
# include <tchar.h>
# pragma warning(push)
# pragma warning (disable : 4996)
#else
# include <dirent.h>
# include <libgen.h>







>
|
>







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

#if (defined _MSC_VER || defined __MINGW32__)
# include <windows.h>
# define _TINYDIR_PATH_MAX MAX_PATH
#elif defined  __linux__
# include <limits.h>

# define _TINYDIR_PATH_MAX PATH_MAX

#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
# include <sys/param.h>
# if defined(BSD)
#  include <limits.h>

#  define _TINYDIR_PATH_MAX PATH_MAX

# endif
#endif

#ifndef _TINYDIR_PATH_MAX
#define _TINYDIR_PATH_MAX 4096
#endif








>
|
>




>
|
>







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





#else
# define _TINYDIR_FUNC static inline
#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 */







>
>
>
>
>

|







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
#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
		if (tinydir_next(dir) == -1)
		{
			goto bail;
		}
	}
	tinydir_close(dir);

	if (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)







|







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

	return 0;
}

_TINYDIR_FUNC
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
{

	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(
#ifdef _MSC_VER
			dir->_f.cFileName
#else
			dir->_e->d_name
#endif

		) + 1 + _TINYDIR_PATH_EXTRA >=
		_TINYDIR_PATH_MAX)
	{
		/* the path for the file will be too long */
		errno = ENAMETOOLONG;
		return -1;
	}
	if (_tinydir_strlen(
#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);

	_tinydir_strcat(file->path, TINYDIR_STRING("/"));
	_tinydir_strcpy(file->name,
#ifdef _MSC_VER
		dir->_f.cFileName
#else
		dir->_e->d_name
#endif
	);
	_tinydir_strcat(file->path, file->name);
#ifndef _MSC_VER
#ifdef __MINGW32__
	if (_tstat(
#else
	if (stat(
#endif
		file->path, &file->_s) == -1)







>














<
|

|

|

>
|






|
<
<
<
<
<
<






>
|
|
<
<
<
<
<
<
|







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

	filename =
#ifdef _MSC_VER
		dir->_f.cFileName;
#else
		dir->_e->d_name;
#endif
	if (_tinydir_strlen(dir->path) +
		_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(filename) >= _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, filename);






	_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
		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);
#else
		_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;
	}









	/* 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);
#endif
















	/* Open the parent directory */
	if (tinydir_open(&dir, dir_name) == -1)
	{
		return -1;
	}








|
|
|
|
|
|

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




<


>
>
>
>
>
>
>
>
>
















|

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







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








#endif

	if (errno)
	{

		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);
#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
  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 - 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)
                                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

*/







|



|
|







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








<
<







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>


#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
#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*/
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,







<
<
<








|







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




#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_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
    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 */
    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 */
    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*/








|












|







144
145
146
147
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 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 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
#    endif
} unz64_s;


#ifndef NOUNCRYPT
#include "crypt.h"
#endif


/* ===========================================================================
     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
   for end of file.
   IN assertion: the stream s has been successfully opened for reading.
*/




















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)
    {
        *pi = (int)c;


        return UNZ_OK;
    }
    else
    {

        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)
{
    for (;;)
    {
        char c1=*(fileName1++);
        char c2=*(fileName2++);
        if ((c1>='a') && (c1<='z'))
            c1 -= 0x20;
        if ((c2>='a') && (c2<='z'))








>

|
<
<


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

<
>
>




>







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

|
<







187
188
189
190
191
192
193
194
195
196
197


198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
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


/* ===========================================================================
   Reads a long in LSB order from the given gz_stream. Sets


*/

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)
    {
        *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)
    {

        *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;
    }
}























































































































/* My own strcmpi / strcasecmp */
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
#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
                                                                or strcasecmp)
   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
        (like 1 on Unix, 2 on Windows)

*/
extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
                                                 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





/*
  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)
{
    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)
        return 0;


    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);

    if (uMaxBack>uSizeFile)
        uMaxBack = uSizeFile;

    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    if (buf==NULL)
        return 0;

    uBackRead = 4;
    while (uBackRead<uMaxBack)
    {
        uLong uReadSize;
        ZPOS64_T uReadPos ;
        int i;







|
|
|

|




|
|
<
<













>
>
>
>




<
|
<




|


|









|







288
289
290
291
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 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 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) {


    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(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=CENTRALDIRINVALID;

    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
        return CENTRALDIRINVALID;


    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);

    if (uMaxBack>uSizeFile)
        uMaxBack = uSizeFile;

    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    if (buf==NULL)
        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
        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;
                break;
            }

        if (uPosFound!=0)
            break;
    }
    TRYFREE(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)
{
    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;

    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
        return 0;


    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);

    if (uMaxBack>uSizeFile)
        uMaxBack = uSizeFile;

    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    if (buf==NULL)
        return 0;

    uBackRead = 4;
    while (uBackRead<uMaxBack)
    {
        uLong uReadSize;
        ZPOS64_T uReadPos;
        int i;







|



|


|








<
<
<
<

|
<




|




|









|







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+(unsigned)i;
                break;
            }

        if (uPosFound!=CENTRALDIRINVALID)
            break;
    }
    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(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=CENTRALDIRINVALID;
    uLong uL;
                ZPOS64_T relativeOffset;

    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
        return CENTRALDIRINVALID;


    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);

    if (uMaxBack>uSizeFile)
        uMaxBack = uSizeFile;

    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    if (buf==NULL)
        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
        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;
                break;
            }

        if (uPosFound!=0)
            break;
    }
    TRYFREE(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 (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return 0;

    /* 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;
    if (uL != 0)
        return 0;

    /* relative offset of the zip64 end of central directory record */
    if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
        return 0;

    /* total number of disks */
    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return 0;
    if (uL != 1)
        return 0;

    /* Goto end of central directory record */
    if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
        return 0;

     /* the signature */
    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return 0;

    if (uL != 0x06064b50)
        return 0;

    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)
{
    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*/
    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]!=' ')







|



|


|
|
|



|



|

|

|

|



|



|

|



|



|


|













|
|
|
<





|
|
|
|







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+(unsigned)i;
                break;
            }

        if (uPosFound!=CENTRALDIRINVALID)
            break;
    }
    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 CENTRALDIRINVALID;

    /* the signature, already checked */
    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return CENTRALDIRINVALID;

    /* 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 CENTRALDIRINVALID;
    if (uL != 0)
        return CENTRALDIRINVALID;

    /* relative offset of the zip64 end of central directory record */
    if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
        return CENTRALDIRINVALID;

    /* total number of disks */
    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return CENTRALDIRINVALID;
    if (uL != 1)
        return CENTRALDIRINVALID;

    /* Goto end of central directory record */
    if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
        return CENTRALDIRINVALID;

     /* the signature */
    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
        return CENTRALDIRINVALID;

    if (uL != 0x06064b50)
        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) {

    unz64_s us;
    unz64_s *s;
    ZPOS64_T central_pos;
    uLong   uL;

    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
                                                 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)
    {
        uLong uS;
        ZPOS64_T uL64;

        us.isZip64 = 1;

        if (ZSEEK64(us.z_filefunc, us.filestream,







|







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!=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
            err=UNZ_ERRNO;

        us.gi.size_comment = 0;
    }
    else
    {
        central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
        if (central_pos==0)
            err=UNZ_ERRNO;

        us.isZip64 = 0;

        if (ZSEEK64(us.z_filefunc, us.filestream,
                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
            err=UNZ_ERRNO;







|







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==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
        *s=us;
        unzGoToFirstFile((unzFile)s);
    }
    return (unzFile)s;
}


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)
{
    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)
{
    return unzOpenInternal(path, NULL, 0);
}

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)
{
    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);
    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)
{
    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)
{
    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)
*/
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_hour = (uInt) ((ulDosDate &0xF800)/0x800);
    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
    ptm->tm_sec =  (uInt) (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,
                                                  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)
{
    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;







|
|
<










|
|
<












|
<



|
<








|
<









|








|
<








|
<










|

|
<


|
|
|

|
|
|





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







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

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

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

    return unzOpenInternal(path, NULL, 0);
}

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

    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);
    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) {

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

    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 easily)
*/
local void unz64local_DosDateToTmuDate(ZPOS64_T ulDosDate, tm_unz* ptm) {

    ZPOS64_T uDate;
    uDate = (ZPOS64_T)(ulDosDate>>16);
    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 = (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(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) {

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







|







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,(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
                                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)
                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.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.disk_num_start == MAXU32)
                                                                {
                                                                        /* Disk Start Number */
                                                                        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
                                                                                err=UNZ_ERRNO;
                                                                }

            }
            else
            {
                if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
                    err=UNZ_ERRNO;
            }







|



















<
<
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|







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,(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)
            {


                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_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 == 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
            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)
                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)







|







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


/*
  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)
{
    return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
                                                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)
{
    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))







|
|
|
|
|
<

|
|
|


|
|
|
|
|
<







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

    return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
                                                 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) {

    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
        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->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)
{
    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)
{
    unz64_s* s;
    int err;

    if (file==NULL)
        return UNZ_PARAMERROR;
    s=(unz64_s*)file;
    if (!s->current_file_ok)







|












|
<



















|
<







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

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

    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
  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)
{
    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;







|
<







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

    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
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)
{
    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(
    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)
{
    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(
    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);







|
<














|
<
<
<










|
<




















|
<
<
<







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

    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(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) {

    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(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
/*
  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)
{
    uLong uMagic,uData,uFlags;
    uLong size_filename;
    uLong size_extra_field;
    int err=UNZ_OK;

    *piSizeVar = 0;
    *poffset_local_extrafield = 0;







|
|
|
<







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

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







|
|
<







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

    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
    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);
        return UNZ_INTERNALERROR;
    }

    pfile_in_zip_read_info->stream_initialised=0;

    if (method!=NULL)
        *method = (int)s->cur_file_info.compression_method;







|







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

        TRYFREE(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
      {

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







>
|



















>
|







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);
        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);
        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
    }
#    endif


    return UNZ_OK;
}

extern int ZEXPORT unzOpenCurrentFile (unzFile file)
{
    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
}

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)
{
    return unzOpenCurrentFile3(file, method, level, raw, NULL);
}

/** Addition for GDAL : START */

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 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)
{
    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;







|
<



|
<



|
<





|
<



















|




|
<







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

    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
}

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

    return unzOpenCurrentFile3(file, method, level, raw, NULL);
}

/** Addition for GDAL : START */

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

    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

        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;

            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 ;








|







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 : (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
            */
            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;



            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;
            if (err!=Z_OK)
                break;
        }
    }

    if (err==Z_OK)
        return iRead;
    return err;
}


/*
  Give the current position in uncompressed data
*/
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)
{

    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)
{
    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;








>
>
>














|






|







|
<













|
<


















|
<







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 : (int)iRead;
            if (err!=Z_OK)
                break;
        }
    }

    if (err==Z_OK)
        return (int)iRead;
    return err;
}


/*
  Give the current position in uncompressed data
*/
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) {


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

    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
  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)
{
    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;







|
<







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

    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
    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)
{
    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;







|
<







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

    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
        (!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);
    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);

    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)
{
    unz64_s* s;
    uLong uReadThis ;
    if (file==NULL)
        return (int)UNZ_PARAMERROR;
    s=(unz64_s*)file;

    uReadThis = uSizeBuf;







|










|












|
<







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


    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;
    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) {

    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

    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)
{
    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)
{
    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)
{
    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)
{
    return unzSetOffset64(file,pos);
}







|
<













|
<








|
<
















|
<


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

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

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

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

    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
#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] */
} 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







|
|
|
|
|
|







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
{
    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
    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));
/*
   Compare two filename (fileName1,fileName2).
   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
                                or strcasecmp)
   If iCaseSenisivity = 0, case sensitivity is defaut 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));
/*
  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));
/*
   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));
/*
   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));
/*
  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 unzGetGlobalInfo64 OF((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));
/*
  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));
/*
  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));
/*
  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));
/*
  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







|
|
|

|
|
|

|




|
|
















|
|





|
|





|






|
|

|
|






|
|
|










|





|






|
|
|







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
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(const char* fileName1,
                                            const char* fileName2,
                                            int iCaseSensitivity);
/*
   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 iCaseSensitivity = 0, case sensitivity is default of your operating system
    (like 1 on Unix, 2 on Windows)
*/


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(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(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(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(unzFile file,
                                    unz_global_info *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(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(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(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(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

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 unzGetCurrentFileInfo OF((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
        the current file
  if szFileName!=NULL, the filemane 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));

/** 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));
/*
  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));
/*
  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));
/*
  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));
/*
  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));
/*
  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));
/*
  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 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 ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
/*
  Give the current position in uncompressed data
*/

extern int ZEXPORT unzeof OF((unzFile file));
/*
  return 1 if the end of file was reached, 0 elsewhere
*/

extern int ZEXPORT unzGetLocalExtrafield OF((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








|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|


|

|











|









|





|
|






|
|
|
|









|
|
|
|
|










|





|
|
|





|





|

|




|




|
|
|







281
282
283
284
285
286
287
288
289
290
291
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(unzFile file,
                                           unz_file_info64 *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 some info about
        the current file
  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(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(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(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(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(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(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(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 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(unzFile file);

extern ZPOS64_T ZEXPORT unztell64(unzFile file);
/*
  Give the current position in uncompressed data
*/

extern int ZEXPORT unzeof(unzFile file);
/*
  return 1 if the end of file was reached, 0 elsewhere
*/

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
         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.
                                 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 <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 */
#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.... */







|










>






<
<














|













<
<
<







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42
43
44
45
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 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>


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




/*
#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
    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 */
    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  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 */
    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;
#endif
} curfile64_info;

typedef struct
{
    zlib_filefunc64_32_def z_filefunc;
    voidpf filestream;        /* io structore 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 */

    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()
{
    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)
{
    while (ldi!=NULL)
    {
        linkedlist_datablock_internal* ldinext = ldi->next_datablock;
        TRYFREE(ldi);
        ldi = ldinext;
    }
}

local void init_linkedlist(linkedlist_data* ll)
{
    ll->first_block = ll->last_block = NULL;
}

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)
{
    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;

    while (len>0)
    {
        uInt copy_this;
        uInt i;
        unsigned char* to_copy;








|






|





|






|






|


|

















|
<












|
<



|




|
<



|
<





|
<














|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206
207

208
209
210
211

212
213
214
215
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
                                     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 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 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;
    unsigned crypt_header_size;
#endif
} curfile64_info;

typedef struct
{
    zlib_filefunc64_32_def z_filefunc;
    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 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(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) {

    while (ldi!=NULL)
    {
        linkedlist_datablock_internal* ldinext = ldi->next_datablock;
        free(ldi);
        ldi = ldinext;
    }
}

local void init_linkedlist(linkedlist_data* ll) {

    ll->first_block = ll->last_block = NULL;
}

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

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

#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)
{
    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)
        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)
{
    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)
{
    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));
}


/****************************************************************************/

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)
{
    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)
{
    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)
{
    uLong x ;
    int i = 0;
    int err;

    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    x = (uLong)i;








<
|
<















|





<
|
<



















|
<






|
|





<
<
|
<




















<
<
|
<


















<
<
|
<







270
271
272
273
274
275
276

277

278
279
280
281
282
283
284
285
286
287
288
289
290
291
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(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,(uLong)nbByte)!=(uLong)nbByte)
        return ZIP_ERRNO;
    else
        return ZIP_OK;
}


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

    uLong year = (uLong)ptm->tm_year;
    if (year>=1980)
        year-=1980;
    else if (year>=80)
        year-=80;
    return
      (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(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(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(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
    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)
{
  ZPOS64_T x;
  int i = 0;
  int err;

  err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
  x = (ZPOS64_T)i;








<

<
|
<







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(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
#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)
{
  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)







<
<
|
<







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(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
    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;
        break;
      }

      if (uPosFound!=0)
        break;
  }
  TRYFREE(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)
{
  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;







|



|
|

|







<
<
|
<







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+(unsigned)i;
        break;
      }

    if (uPosFound!=0)
      break;
  }
  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(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
      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;
        break;
      }
    }

      if (uPosFound!=0)
        break;
  }

  TRYFREE(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 */
  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)







|








|











|







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+(unsigned)i;
        break;
      }
    }

      if (uPosFound!=0)
        break;
  }

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

  if (uL != 0x06064b50) // signature of 'Zip64 end of central directory'
    return 0;

  return relativeOffset;
}

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*/
  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;







|
<








|
|
|
|







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

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 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
        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);
  }
  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)
{
    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)







|















|
<







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;
    }
    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) {

    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
      *globalcomment = ziinit.globalcomment;
    }
#    endif /* !NO_ADDFILEINEXISTINGZIP*/

    if (err != ZIP_OK)
    {
#    ifndef NO_ADDFILEINEXISTINGZIP
        TRYFREE(ziinit.globalcomment);
#    endif /* !NO_ADDFILEINEXISTINGZIP*/
        TRYFREE(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)
{
    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)
{
    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)
{
    return zipOpen3((const void*)pathname,append,NULL,NULL);
}

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)
{
  /* 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);








|

|









|
<










|
<














|
<



|
<



|
<







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
        free(ziinit.globalcomment);
#    endif /* !NO_ADDFILEINEXISTINGZIP*/
        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) {

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

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

    return zipOpen3((const void*)pathname,append,NULL,NULL);
}

extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) {

    return zipOpen3(pathname,append,NULL,NULL);
}

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
      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)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)
{
    zip64_internal* zi;
    uInt size_filename;
    uInt size_comment;
    uInt i;
    int err = ZIP_OK;

#    ifdef NOCRYPT







|
|
















|
|
|
|
|
|
|
<







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, (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) {

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












    zi = (zip64_internal*)file;

    if (zi->in_opened_file_inzip == 1)
    {
        err = zipCloseFileInZip (file);
        if (err != ZIP_OK)







>
>
>
>
>
>
>
>
>
>
>







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
#    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    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)
{
    int err=ZIP_OK;

    if (zi->ci.encrypt != 0)
    {
#ifndef NOCRYPT
        uInt i;
        int t;







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


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







|
<
|
|
|
|
|
|





|
<
|
|
|
|
|
|



|
|
|
<
|
|
|
|
|
|


|
|
|
|
<
|
|
|
|
|
|


|
|
|
|
<
|
|
|
|
|
|


|
<







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

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

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

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

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

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

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

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

    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


    zi->ci.pos_in_buffered_data = 0;

    return err;
}

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;








|
<







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

    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

      if(err == BZ_RUN_OK)
        err = ZIP_OK;
    }
    else
#endif
    {
      zi->ci.stream.next_in = (Bytef*)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)







|




















<
<
<
<
<







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*)(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);






              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
          }
      }// while(...)
    }

    return err;
}

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)
{
    zip64_internal* zi;
    ZPOS64_T compressed_size;
    uLong invalidValue = 0xffffffff;
    short datasize = 0;
    int err=ZIP_OK;

    if (file == NULL)
        return ZIP_PARAMERROR;
    zi = (zip64_internal*)file;

    if (zi->in_opened_file_inzip == 0)







|
<



|
<



|







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

    return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);
}

extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) {

    zip64_internal* zi;
    ZPOS64_T compressed_size;
    uLong invalidValue = 0xffffffff;
    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

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







|







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

    zi->number_entry ++;
    zi->in_opened_file_inzip = 0;

    return err;
}

extern int ZEXPORT zipCloseFileInZip (zipFile file)
{
    return zipCloseFileInZipRaw (file,0,0);
}

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)
{
  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' */







|
<



|
<




















|
<







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

    return zipCloseFileInZipRaw (file,0,0);
}

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

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

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







<
|
>







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


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
    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)
{
  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)
{
    zip64_internal* zi;
    int err = 0;
    uLong size_centraldir = 0;
    ZPOS64_T centraldir_pos_inzip;
    ZPOS64_T pos;

    if (file == NULL)







|
<
















|
<







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

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

    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
            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)
    {
      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);
#endif
    TRYFREE(zi);

    return err;
}

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)
    return ZIP_PARAMERROR;

  pNewHeader = (char*)ALLOC(*dataLen);
  pTmp = pNewHeader;

  while(p < (pData + *dataLen))
  {
    header = *(short*)p;
    dataSize = *(((short*)p)+1);








|


















|

|




|
<









|


|







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)
    {
      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
    free(zi->globalcomment);
#endif
    free(zi);

    return err;
}

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 == NULL || *dataLen < 4)
    return ZIP_PARAMERROR;

  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
    *dataLen = size;

    retVal = ZIP_OK;
  }
  else
    retVal = ZIP_ERRNO;

  TRYFREE(pNewHeader);

  return retVal;
}







|



1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
    *dataLen = size;

    retVal = ZIP_OK;
  }
  else
    retVal = ZIP_ERRNO;

  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
#  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] */
} 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));
/*
  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
*/

extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
                                   int append,
                                   zipcharpc* globalcomment,
                                   zlib_filefunc_def* pzlib_filefunc_def));

extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,
                                   int append,
                                   zipcharpc* globalcomment,
                                   zlib_filefunc64_def* pzlib_filefunc_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 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));

/*
  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
  if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
    contains the extrafield data the the local 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_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));
/*
  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_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
                                            ));

/*
  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_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
                                            ));
/*
  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));
/*
  Write data in the zipfile
*/

extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
/*
  Close the current file in the zipfile
*/

extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
                                            uLong uncompressed_size,
                                            uLong crc32));

extern int ZEXPORT zipCloseFileInZipRaw64 OF((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));
/*
  Close the zipfile
*/


extern int ZEXPORT zipRemoveExtraInfoBlock OF((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.








|
|
|
|
|
|



















|
|
















|


|
|
|
|

|


|

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

|
|
|
|
|
|
|
|
|
|
|






|

|









|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|




|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

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








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


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







|
|
|




|




|
|
|

|
|
|







|
|





|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286
287
288
289
290
291
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
{
    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(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 course, you can use RAW reading and writing to copy the file you did not want delete
*/

extern zipFile ZEXPORT zipOpen2(const char *pathname,
                                int append,
                                zipcharpc* globalcomment,
                                zlib_filefunc_def* pzlib_filefunc_def);

extern zipFile ZEXPORT zipOpen2_64(const void *pathname,
                                   int append,
                                   zipcharpc* globalcomment,
                                   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(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(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 for the local header
  if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
    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(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(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(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(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(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(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(zipFile file,
                                       const void* buf,
                                       unsigned len);
/*
  Write data in the zipfile
*/

extern int ZEXPORT zipCloseFileInZip(zipFile file);
/*
  Close the current file in the zipfile
*/

extern int ZEXPORT zipCloseFileInZipRaw(zipFile file,
                                        uLong 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(zipFile file,
                            const char* global_comment);
/*
  Close the zipfile
*/


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
(* 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_VERNUM  = $12a0;

type
  alloc_func = function(opaque: Pointer; items, size: Integer): Pointer;
                 cdecl;
  free_func  = procedure(opaque, address: Pointer);
                 cdecl;












|







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








|







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







|







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







|
|
|
|







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 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
 * - 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
 *   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).







|







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 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
        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 (put && ret == 0) {
        if (fail)
            destlen >>= 1;
        dest = malloc(destlen);
        if (dest == NULL) {
            fprintf(stderr, "memory allocation failure\n");
            free(source);







|







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

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

    if (argc>=3)
        BlockSizeCompress=atol(argv[2]);

    if (argc>=4)
        BlockSizeUncompress=atol(argv[3]);








|







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, %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
/*
 * untgz.c -- Display contents and extract files from a gzip'd TAR file
 *
 * written by Pedro A. Aranda Gutierrez <[email protected]>
 * adaptation to Unix by Jean-loup Gailly <[email protected]>
 * various fixes by Cosmin Truta <[email protected]>
















 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>

#include "zlib.h"

#ifdef unix
#  include <unistd.h>
#else
#  include <direct.h>
#  include <io.h>
#endif

#ifdef WIN32
#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 <utime.h>
#endif


/* values used in typeflag field */

#define REGTYPE  '0'            /* regular file */






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










|
<
<


<
<
<
|










>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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 <[email protected]>
 * adaptation to Unix by Jean-loup Gailly <[email protected]>
 * various fixes by Cosmin Truta <[email protected]>
 *
 * 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 _WIN32


#  include <direct.h>
#  include <io.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
  char              *fname;
  int                mode;
  time_t             time;
};

enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID };

char *TGZfname          OF((const char *));
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 **));

int ExprMatch           OF((char *, char *));

int makedir             OF((char *));
int matchname           OF((int, int, char **, char *));

void error              OF((const char *));
int tar                 OF((gzFile, int, int, int, char **));

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)







|
<

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







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 *prog;







void error(const char *msg)

{


  fprintf(stderr, "%s: %s\n", prog, msg);


  exit(1);


}


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
}


/* set file time */

int setfiletime (char *fname,time_t ftime)
{
#ifdef WIN32
  static int isWinNT = -1;
  SYSTEMTIME st;
  FILETIME locft, modft;
  struct tm *loctm;
  HANDLE hFile;
  int result;








|







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

    prog = strrchr(argv[0],'\\');
    if (prog == NULL)
      {
        prog = strrchr(argv[0],'/');
        if (prog == NULL)
          {







<
<
<
<
<
<












|







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);
}








/* ============================================================ */

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

    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
Building instructions for the DLL versions of Zlib 1.2.11
========================================================

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
|


















<
<
<







1
2
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.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



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








Important
---------
- To use zlibwapi.dll in your application, you must define the
  macro ZLIB_WINAPI when compiling your application's source files.








>
>
>
>
>
>







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
  has a slightly different effect. To avoid compatibility problems, do
  not define it here.


Gilles Vollant
[email protected]

Visual Studio 2013 and 2015 Projects from Sean Hunt
[email protected]







|

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
[email protected]

Visual Studio 2013, 2015, and 2022 Projects from Sean Hunt
[email protected]

Changes to compat/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters.

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





|







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





|







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</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
    <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>
      <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>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>







|












|







177
178
179
180
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>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>%(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
  </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>
      <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>
      <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>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>







|












|














|






|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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>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>
    </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|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
      <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>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|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
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineIA64</TargetMachine>
    </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|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
  </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>







<
<
<
<
<
<
<
<












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="..\..\..\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
<?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>
    </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>





|







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







<
<
<







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="..\..\..\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
<?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>
    </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>





|







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</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
#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 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 "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"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END




|
|













|




|







1
2
3
4
5
6
7
8
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

Changes to compat/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.

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







|







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







<
<
<
<




|
|


















|



<
<
<
<




|







178
179
180
181
182
183
184




185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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>




  </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>
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <Midl>
      <TargetEnvironment>X64</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(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>







|







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>..\..\..;%(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
      <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>
      <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>







<
<
<
<







|







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>




  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
310
311
312
313
314
315
316
317
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
  </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>
      <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>
      <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>
      <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>







|
|


















|



<
<
<
<







|







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>..\..\..;%(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|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
    <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" />







<
<
<
<
<
<
<
<







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="..\..\..\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
    </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">







<
<
<







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="..\..\..\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
LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5



|







1
2
3
4
5
6
7
8
9
10
11
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
147
148
149
150
151
152
153





        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175












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







|
|




















|









<
<
<
<











|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
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>..\..\..;%(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>%(AdditionalDependencies)</AdditionalDependencies>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
    </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>
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
      <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>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>







|
|







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>..\..\..;%(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
    </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>
      <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>
      <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>
      <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>
      <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>







|









<
<
<
<











|
|



















|







<
<
<
<











|







304
305
306
307
308
309
310
311
312
313
314
315
316
317
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>%(AdditionalDependencies)</AdditionalDependencies>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateMapFile>true</GenerateMapFile>
      <SubSystem>Windows</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>
    </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>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <GenerateMapFile>true</GenerateMapFile>
      <SubSystem>Windows</SubSystem>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>




  </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>..\..\..;%(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
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
      <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>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>







|
|







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>..\..\..;%(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
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(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>
      <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>







|







<
<
<
<











|







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>%(AdditionalDependencies)</AdditionalDependencies>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
      <ModuleDefinitionFile>.\zlibvc.def</ModuleDefinitionFile>
      <GenerateMapFile>true</GenerateMapFile>
      <SubSystem>Windows</SubSystem>
      <TargetMachine>MachineX64</TargetMachine>
    </Link>




  </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>..\..\..;%(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
    <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" />







<
<
<
<
<
<
<
<







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="..\..\..\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
    </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">







<
<
<







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="..\..\..\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
    <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>
      <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>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>







|












|







183
184
185
186
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>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>
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
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>
      <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>
      <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>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>







|












|














|






|







243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
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>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>
    </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|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
      <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>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|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
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineIA64</TargetMachine>
    </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|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
  </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>







<
<
<
<
<
<
<
<












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="..\..\..\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
#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 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 "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"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END




|
|













|




|







1
2
3
4
5
6
7
8
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

Changes to compat/zlib/contrib/vstudio/vc11/zlibstat.vcxproj.

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







|







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>..\..\..;%(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
      <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>
      <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>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|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;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|
|


















|







|







189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
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>..\..\..;%(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>
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>
      <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>







|







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>..\..\..;%(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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
305
306
307
308
309
310
311
312
313
314
315
316
317
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>
      <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>
      <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>
      <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>







|
|


















|










|







305
306
307
308
309
310
311
312
313
314
315
316
317
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>..\..\..;%(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|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
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>
      <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
  </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>
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>
      <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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
    <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" />







<
<
<
<
<
<
<
<







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="..\..\..\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
LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5



|







1
2
3
4
5
6
7
8
9
10
11
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
147
148
149
150
151
152
153





        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175












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







|
|




















|













<
<
<
<











|







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
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>..\..\..;%(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>
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
      <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>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>







|
|







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>..\..\..;%(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
    </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>
      <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>
      <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>
      <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>
      <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>







|













<
<
<
<











|
|



















|











<
<
<
<











|







319
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>%(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>




  </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|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>..\..\..;%(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
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
      <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>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>







|
|







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>..\..\..;%(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
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(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>
      <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>







|











<
<
<
<











|







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>%(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|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>..\..\..;%(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
    <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" />







<
<
<
<
<
<
<
<







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="..\..\..\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
    <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>
      <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>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>







|












|







186
187
188
189
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>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>
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
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>
      <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>
      <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>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>







|












|















|






|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
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>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|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
      <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>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|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
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineIA64</TargetMachine>
    </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|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
  </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>







<
<
<
<
<
<
<
<












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="..\..\..\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
#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 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 "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"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END




|
|













|




|







1
2
3
4
5
6
7
8
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

Changes to compat/zlib/contrib/vstudio/vc12/zlibstat.vcxproj.

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







|







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>..\..\..;%(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
      <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>
      <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>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|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;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|
|


















|







|







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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>..\..\..;%(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>
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>
      <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>







|







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>..\..\..;%(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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
308
309
310
311
312
313
314
315
316
317
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>
      <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>
      <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>
      <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>







|
|


















|










|







308
309
310
311
312
313
314
315
316
317
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>..\..\..;%(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|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
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>
      <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
  </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>
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>
      <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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
    <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" />







<
<
<
<
<
<
<
<







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="..\..\..\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
LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5



|







1
2
3
4
5
6
7
8
9
10
11
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
147
148
149
150
151
152
153





        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175












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







|
|




















|













<
<
<
<











|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
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>..\..\..;%(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>
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
      <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>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>







|
|







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>..\..\..;%(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
    </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>
      <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>
      <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>
      <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>
      <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>







|














<
<
<
<











|
|



















|











<
<
<
<











|







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>%(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|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>..\..\..;%(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
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
      <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>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>







|
|







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>..\..\..;%(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
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(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>
      <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>







|











<
<
<
<











|







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>%(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|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>..\..\..;%(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
    <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" />







<
<
<
<
<
<
<
<







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="..\..\..\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
    <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>
      <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>
      <OutputFile>$(OutDir)testzlib.exe</OutputFile>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <ProgramDatabaseFile>$(OutDir)testzlib.pdb</ProgramDatabaseFile>
      <SubSystem>Console</SubSystem>
      <RandomizedBaseAddress>false</RandomizedBaseAddress>
      <DataExecutionPrevention>
      </DataExecutionPrevention>







|












|







186
187
188
189
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>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>
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
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>
      <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>
      <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>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>







|












|















|






|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
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>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|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
      <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>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
    </ClCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|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
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <TargetMachine>MachineIA64</TargetMachine>
    </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|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
  </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>







<
<
<
<
<
<
<
<












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="..\..\..\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
#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 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 "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"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END




|
|













|




|







1
2
3
4
5
6
7
8
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

Changes to compat/zlib/contrib/vstudio/vc14/zlibstat.vcxproj.

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







|







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>..\..\..;%(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
      <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>
      <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>
      <OutputFile>$(OutDir)zlibstat.lib</OutputFile>
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </Lib>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|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;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|
|


















|







|







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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>..\..\..;%(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>
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>
      <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>







|







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>..\..\..;%(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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</TargetEnvironment>
    </Midl>
    <ClCompile>
      <Optimization>Disabled</Optimization>
      <AdditionalIncludeDirectories>..\..\..;..\..\masmx86;%(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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
308
309
310
311
312
313
314
315
316
317
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>
      <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>
      <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>
      <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>







|
|


















|










|







308
309
310
311
312
313
314
315
316
317
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>..\..\..;%(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|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
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>
      <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
  </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>
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>
      <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
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseWithoutAsm|Itanium'">
    <Midl>
      <TargetEnvironment>Itanium</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>
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
    <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" />







<
<
<
<
<
<
<
<







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="..\..\..\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
LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5



|







1
2
3
4
5
6
7
8
9
10
11
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
147
148
149
150
151
152
153





        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175












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







|
|




















|













<
<
<
<











|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
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>..\..\..;%(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>
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
      <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>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>







|
|







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>..\..\..;%(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
    </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>
      <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>
      <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>
      <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>
      <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>







|














<
<
<
<











|
|



















|











<
<
<
<











|







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>%(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|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>..\..\..;%(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
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>X64</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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
      <MkTypLibCompatible>true</MkTypLibCompatible>
      <SuppressStartupBanner>true</SuppressStartupBanner>
      <TargetEnvironment>Itanium</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;WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>







|







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>..\..\..;%(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
      <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>
      <StringPooling>true</StringPooling>
      <ExceptionHandling>
      </ExceptionHandling>
      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
      <BufferSecurityCheck>false</BufferSecurityCheck>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <PrecompiledHeaderOutputFile>$(IntDir)zlibvc.pch</PrecompiledHeaderOutputFile>







|
|







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>..\..\..;%(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
      <SuppressStartupBanner>true</SuppressStartupBanner>
    </ClCompile>
    <ResourceCompile>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <Culture>0x040c</Culture>
    </ResourceCompile>
    <Link>
      <AdditionalDependencies>..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(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>
      <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>







|











<
<
<
<











|







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>%(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|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>..\..\..;%(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
    <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" />







<
<
<
<
<
<
<
<







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="..\..\..\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
		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
			>
			<File
				RelativePath="..\..\minizip\miniunz.c"
				>
			</File>
		</Filter>
		<Filter







|







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"
			>
			<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
		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
			>
			<File
				RelativePath="..\..\minizip\minizip.c"
				>
			</File>
		</Filter>
		<Filter







|







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"
			>
			<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
			<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"
				MinimalRebuild="true"
				BasicRuntimeChecks="0"
				RuntimeLibrary="1"
				BufferSecurityCheck="false"
				UsePrecompiledHeader="0"
				AssemblerOutput="4"
				AssemblerListingLocation="$(IntDir)\"







|







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







<







67
68
69
70
71
72
73

74
75
76
77
78
79
80
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"

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







|
















<







123
124
125
126
127
128
129
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="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"

				GenerateManifest="false"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
			/>
			<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"
				StringPooling="true"
				BasicRuntimeChecks="0"
				RuntimeLibrary="0"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				UsePrecompiledHeader="0"
				AssemblerListingLocation="$(IntDir)\"







|







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







<







534
535
536
537
538
539
540

541
542
543
544
545
546
547
				Name="VCResourceCompilerTool"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"

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







|
















<







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

				GenerateManifest="false"
			/>
			<Tool
				Name="VCALinkTool"
			/>
			<Tool
				Name="VCManifestTool"
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
			>
			<File
				RelativePath="..\..\..\adler32.c"
				>
			</File>
			<File
				RelativePath="..\..\..\compress.c"







|







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







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







748
749
750
751
752
753
754




















































755
756
757
758
759
760
761
				>
			</File>
			<File
				RelativePath="..\..\..\infback.c"
				>
			</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
		</Configuration>
	</Configurations>
	<References>
	</References>
	<Files>
		<Filter
			Name="Source Files"
			Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
			>
			<File
				RelativePath="..\..\testzlib\testzlib.c"
				>
			</File>
		</Filter>
		<Filter







|







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"
			>
			<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
#include <windows.h>

#define IDR_VERSION1  1
IDR_VERSION1	VERSIONINFO	MOVEABLE IMPURE LOADONCALL DISCARDABLE
  FILEVERSION	 1, 2, 11, 0
  PRODUCTVERSION 1, 2, 11, 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 "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"
    END
  END
  BLOCK "VarFileInfo"
  BEGIN
    VALUE "Translation", 0x0409, 1252
  END
END




|
|













|




|







1
2
3
4
5
6
7
8
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

Changes to compat/zlib/contrib/vstudio/vc9/zlibstat.vcproj.

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"
				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)\"







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				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
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="3"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				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)\"







|







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="..\..\.."
				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
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="2"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				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
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="2"
			/>
			<Tool
				Name="VCCLCompilerTool"
				Optimization="0"
				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
			/>
			<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"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
				AssemblerListingLocation="$(IntDir)\"







|
|







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="..\..\.."
				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
			/>
			<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







<







291
292
293
294
295
296
297

298
299
300
301
302
303
304
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLibrarianTool"
				AdditionalOptions="/MACHINE:X86 /NODEFAULTLIB"

				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
			<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"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"
				AssemblerListingLocation="$(IntDir)\"







|
|







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="..\..\.."
				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
			/>
			<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







<







365
366
367
368
369
370
371

372
373
374
375
376
377
378
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLibrarianTool"
				AdditionalOptions="/MACHINE:AMD64 /NODEFAULTLIB"

				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
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="2"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				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"







|







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="..\..\.."
				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
			/>
			<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"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"







|







485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
			/>
			<Tool
				Name="VCMIDLTool"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				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
			<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;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibstat.pch"







|







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="..\..\.."
				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
			<Tool
				Name="VCMIDLTool"
				TargetEnvironment="2"
			/>
			<Tool
				Name="VCCLCompilerTool"
				InlineFunctionExpansion="1"
				AdditionalIncludeDirectories="..\..\..;..\..\masmx86"
				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"







|







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="..\..\.."
				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
				>
			</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>







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







727
728
729
730
731
732
733




















































734
735
736
737
738
739
740
				>
			</File>
			<File
				RelativePath="..\..\..\infback.c"
				>
			</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
LIBRARY
; zlib data compression and ZIP file I/O library

VERSION		1.2

EXPORTS
        adler32                                  @1
        compress                                 @2
        crc32                                    @3
        deflate                                  @4
        deflateCopy                              @5



|







1
2
3
4
5
6
7
8
9
10
11
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
147
148
149
150
151
152
153





        inflateValidate                         @169
        uncompress2                             @170
        gzfread                                 @171
        gzfwrite                                @172
        deflateGetDictionary                    @173
        adler32_z                               @174
        crc32_z                                 @175












>
>
>
>
>
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
				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"
				ExceptionHandling="0"
				RuntimeLibrary="1"
				BufferSecurityCheck="false"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerListingLocation="$(IntDir)\"
				ObjectFile="$(IntDir)\"
				ProgramDataBaseFileName="$(OutDir)\"







|
|







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="..\..\.."
				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
			/>
			<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"







<







77
78
79
80
81
82
83

84
85
86
87
88
89
90
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="/MACHINE:I386"

				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
				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"
				ExceptionHandling="0"
				RuntimeLibrary="3"
				BufferSecurityCheck="false"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerListingLocation="$(IntDir)\"
				ObjectFile="$(IntDir)\"
				ProgramDataBaseFileName="$(OutDir)\"







|
|







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="..\..\.."
				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
				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"







<







172
173
174
175
176
177
178

179
180
181
182
183
184
185
				Culture="1036"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"

				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
				SuppressStartupBanner="true"
				TargetEnvironment="2"
				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;WIN64"
				ExceptionHandling="0"
				RuntimeLibrary="3"
				BufferSecurityCheck="false"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerListingLocation="$(IntDir)\"
				ObjectFile="$(IntDir)\"







|







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="..\..\.."
				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
				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"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"







|







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="..\..\.."
				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
				SuppressStartupBanner="true"
				TargetEnvironment="3"
				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;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"







|







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="..\..\.."
				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
				SuppressStartupBanner="true"
				TargetEnvironment="2"
				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;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"







|







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="..\..\.."
				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
				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"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="0"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerOutput="2"







|
|







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="..\..\.."
				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
			/>
			<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"







<







660
661
662
663
664
665
666

667
668
669
670
671
672
673
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"
				AdditionalOptions="/MACHINE:I386"

				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
				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"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"
				AssemblerOutput="2"







|
|







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="..\..\.."
				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
				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"







<







759
760
761
762
763
764
765

766
767
768
769
770
771
772
				Culture="1036"
			/>
			<Tool
				Name="VCPreLinkEventTool"
			/>
			<Tool
				Name="VCLinkerTool"

				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
				SuppressStartupBanner="true"
				TargetEnvironment="2"
				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;WIN64"
				StringPooling="true"
				ExceptionHandling="0"
				RuntimeLibrary="2"
				BufferSecurityCheck="false"
				EnableFunctionLevelLinking="true"
				PrecompiledHeaderFile="$(IntDir)/zlibvc.pch"







|







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="..\..\.."
				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
				>
			</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>







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







942
943
944
945
946
947
948




















































949
950
951
952
953
954
955
				>
			</File>
			<File
				RelativePath="..\..\..\infback.c"
				>
			</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
/* crc32.c -- compute the CRC-32 of a data stream
 * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 *
 * Thanks to Rodney Brown <[email protected]> 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
 * 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
  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.

 */

#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 */












/* Definitions for doing the crc four data bytes at a time. */








#if !defined(NOBYFOUR) && defined(Z_U4)
































#  define BYFOUR


#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,
                        const unsigned char FAR *, z_size_t));


#  define TBLS 8




































#else




#  define TBLS 1
#endif /* BYFOUR */



/* 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));










#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));

#ifdef MAKECRCH
   local void write_table OF((FILE *, const z_crc_t FAR *));


#endif /* MAKECRCH */

/*














































































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

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

    /* 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;

        /* 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]);

        /* 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;
        }

#ifdef BYFOUR
        /* 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_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 */

        crc_table_empty = 0;
    }

    else {      /* not first */
        /* wait for the other guy to finish (not efficient, but rare) */
        while (crc_table_empty)


            ;
    }





#ifdef MAKECRCH
    /* write out CRC tables to crc32.h */
    {









        FILE *out;




        out = fopen("crc32.h", "w");
        if (out == NULL) return;



        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 ");
        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");































        fclose(out);
    }
#endif /* MAKECRCH */
}

#ifdef MAKECRCH





local void write_table(out, table)

    FILE *out;


    const z_crc_t FAR *table;


{





    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" : ", "));
}
#endif /* MAKECRCH */















#else /* !DYNAMIC_CRC_TABLE */





/* ========================================================================

 * Tables of CRC-32s of all single-byte values, made by make_crc_table().




 */














#include "crc32.h"
#endif /* DYNAMIC_CRC_TABLE */

/* =========================================================================
 * This function can be used by asm versions of crc32()

 */
const z_crc_t FAR * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
    if (crc_table_empty)
        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













/* ========================================================================= */
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;

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



        endian = 1;
        if (*((unsigned char *)(&endian)))

            return crc32_little(crc, buf, len);
        else
            return crc32_big(crc, buf, len);
    }
#endif /* BYFOUR */
    crc = crc ^ 0xffffffffUL;
    while (len >= 8) {
        DO8;
        len -= 8;


    }
    if (len) do {
        DO1;


    } while (--len);
    return crc ^ 0xffffffffUL;
}














/* ========================================================================= */
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
   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.
 */






/* ========================================================================= */

#define DOLIT4 c ^= *buf4++; \
        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


/* ========================================================================= */
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;









    c = (z_crc_t)crc;
    c = ~c;

    while (len && ((ptrdiff_t)buf & 3)) {
        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
        len--;

    }

    buf4 = (const z_crc_t FAR *)(const void FAR *)buf;

    while (len >= 32) {
        DOLIT32;
        len -= 32;

    }




    while (len >= 4) {
        DOLIT4;

        len -= 4;
    }
    buf = (const unsigned char FAR *)buf4;








    if (len) do {
        c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
    } while (--len);
    c = ~c;
    return (unsigned long)c;










}

/* ========================================================================= */
#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]
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4











/* ========================================================================= */
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;
    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;
    }
    while (len >= 4) {
        DOBIG4;
        len -= 4;
    }


    buf = (const unsigned char FAR *)buf4;

    if (len) do {
        c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);








    } while (--len);
    c = ~c;
    return (unsigned long)(ZSWAP32(c));
}


#endif /* BYFOUR */


#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;
{
    unsigned long sum;




















    sum = 0;
    while (vec) {
        if (vec & 1)
            sum ^= *mat;
        vec >>= 1;
        mat++;
    }





    return sum;
}

/* ========================================================================= */
local void gf2_matrix_square(square, mat)
    unsigned long *square;
    unsigned long *mat;
{
    int n;

    for (n = 0; n < GF2_DIM; n++)
        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;
    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;

    /* 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;
    }

    /* put operator for two zero bits in even */










    gf2_matrix_square(even, odd);





    /* 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 {
        /* 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 */
        if (len2 == 0)
            break;





        /* another iteration of the loop with odd and even swapped */

        gf2_matrix_square(odd, even);

        if (len2 & 1)
            crc1 = gf2_matrix_times(odd, crc1);
        len2 >>= 1;









        /* if no more bits set, then done */
    } while (len2 != 0);



    /* return combined crc */
    crc1 ^= crc2;

    return crc1;
}









/* ========================================================================= */
uLong ZEXPORT crc32_combine(crc1, crc2, len2)

    uLong crc1;

    uLong crc2;
    z_off_t len2;

{


    return crc32_combine_(crc1, crc2, len2);
}


uLong ZEXPORT crc32_combine64(crc1, crc2, len2)





    uLong crc1;

    uLong crc2;
    z_off64_t len2;

{

    return crc32_combine_(crc1, crc2, len2);

}

|


|
|
|
<
<







|



|
>









|

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

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

>
>
>
>
|
|

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

|
>
>
>
|
>
>
|
>
|
>

|
>
>

>

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




|

|

|



|

|
|
|
|

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

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


<

>
>
>
>
>
>
>
>
>

>
>
>



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






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


|
|
|
|

|
>
>
>
>
>
>
>
>
>

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

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



|
>

|
<

<
|




|
|
>
>
|
>
>
>
>
>

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

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

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

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


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

<
<
>
|
<
|
>
|

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

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

>
>
>
>
>
>
>
|
>

|
>
|
>
|
<
>
|
>
>
|


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

1
2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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-2022 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 *
 * 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.


 */

/* @(#) $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
  first call get_crc_table() to initialize the tables before allowing more than
  one thread to use crc32().

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

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


/* 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().
 */
#  include "crc32.h"
#endif

/* CRC polynomial. */
#define POLY 0xedb88320         /* p(x) reflected, with x^32 implied */

/*
  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
/* =========================================================================
 * 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(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
  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
  polynomial q, also with the lowest power in the most significant bit (so the
  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
  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.

  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.


 */








local void make_crc_table(void) {





    unsigned i, j, n;



    z_crc_t p;

    /* 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 W



        crc_big_table[i] = byte_swap(p);







#endif
    }


    /* initialize the x^2^n mod p(x) table */
    p = (z_crc_t)1 << 30;         /* x^1 */

    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

    {
        /*
          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,
            "/* 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"

            "    ");
        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(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 < k; n++)
        fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : "    ",
                (unsigned long)(table[n] >> 32),
                n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
}

/*
  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" : ", "));
}

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

#endif /* DYNAMIC_CRC_TABLE */

/* =========================================================================
 * 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(void) {

#ifdef DYNAMIC_CRC_TABLE

    once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */
    return (const z_crc_t FAR *)crc_table;
}

/* =========================================================================
 * 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(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
    once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */

    /* Pre-condition the CRC */
    crc = (~crc) & 0xffffffff;



    /* Compute the CRC up to a word boundary. */

    while (len && ((z_size_t)buf & 7) != 0) {

        len--;
        val = *buf++;
        __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
    }


    /* 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));
        }


        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




/*
  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;
}

local z_word_t crc_word_big(z_word_t data) {
    int k;

    for (k = 0; k < W; k++)
        data = (data << 8) ^
            crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
    return data;
}

#endif

/* ========================================================================= */


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;



        /* Compute the CRC up to a z_word_t boundary. */
        while (len && ((z_size_t)buf & (W - 1)) != 0) {

            len--;
            crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
        }


        /* Compute the CRC on as many N z_word_t blocks as are available. */
        blks = len / (N * W);

        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;

        if (*(unsigned char *)&endian) {
            /* Little endian. */


            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

            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. */


            crc0 = crc;
#if N > 1
            crc1 = 0;

#if N > 2
            crc2 = 0;
#if N > 3
            crc3 = 0;
#if N > 4
            crc4 = 0;
#if N > 5
            crc5 = 0;
#endif
#endif
#endif




#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];

#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

#endif

#endif

#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



#endif
#endif
#endif
#endif
                }

            }

            /*
              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. */


            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
            crc1 = 0;

#if N > 2
            crc2 = 0;
#if N > 3


            crc3 = 0;
#if N > 4
            crc4 = 0;
#if N > 5
            crc5 = 0;
#endif

#endif





#endif
#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];
#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_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

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

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


            }

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

#endif
#endif
#endif
#endif
            words += N;
            crc = byte_swap(comb);
        }



        /*
          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) {

        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];
    }

    while (len) {
        len--;
        crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
    }


    /* 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_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);

}

/* ========================================================================= */
uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) {
    return crc32_combine64(crc1, crc2, (z_off64_t)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
/* 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,
    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
































  },
  {
    0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
    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





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





















































































  },
  {
    0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
    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,
    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
#endif
  }







};




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

|
>
>
>
>
>
>
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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[] = {
    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 */


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

   {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000,

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

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


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

   {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000,

    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,

    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
/* deflate.c -- compress data using the deflation algorithm
 * Copyright (C) 1995-2017 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

|







1
2
3
4
5
6
7
8
9
/* deflate.c -- compress data using the deflation algorithm
 * 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
 */

/* @(#) $Id$ */

#include "deflate.h"

const char deflate_copyright[] =
   " deflate 1.2.11 Copyright 1995-2017 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));
/* 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));
#ifndef FASTEST
local block_state deflate_slow   OF((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 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 */







|







<
<
<







|


<
<
<
|
|

|

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







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62



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.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.
 */




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)(deflate_state *s, int flush);
/* Compression function. Returns the block state after the call. */




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(deflate_state *s, int flush);
#endif
local block_state deflate_rle(deflate_state *s, int flush);
local block_state deflate_huff(deflate_state *s, int flush);

















/* ===========================================================================
 * Local data
 */

#define NIL 0
/* Tail of hash chains */
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

/* ===========================================================================
 * 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)


/* ===========================================================================
 * 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







|







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)


/* ===========================================================================
 * 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
#endif

/* ===========================================================================
 * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
 * prev[] will be initialized on the fly.
 */
#define CLEAR_HASH(s) \

    s->head[s->hash_size-1] = NIL; \
    zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));



/* ===========================================================================
 * 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.
 */





local void slide_hash(s)
    deflate_state *s;
{
    unsigned n, m;
    Posf *p;
    uInt wsize = s->w_size;

    n = s->hash_size;
    p = &s->head[n];
    do {







>
|
|
>
>






>
>
>
>
>
|
<
<







164
165
166
167
168
169
170
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)); \
    } 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(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
        *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
}
































































































































































/* ========================================================================= */
int ZEXPORT deflateInit_(strm, level, version, stream_size)
    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,
                  version, stream_size)
    z_streamp strm;
    int  level;
    int  method;
    int  windowBits;
    int  memLevel;
    int  strategy;
    const char *version;
    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;







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


<
<
<
|
|
<






|
<
<
<
<
|
<
<
|
<
<




<
<
<
<
<







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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_(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_(z_streamp strm, int level, int method,




                          int windowBits, int memLevel, int strategy,


                          const char *version, int stream_size) {


    deflate_state *s;
    int wrap = 1;
    static const char my_version[] = ZLIB_VERSION;






    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
    if (level != 0) level = 1;
#else
    if (level == Z_DEFAULT_COMPRESSION) level = 6;
#endif

    if (windowBits < 0) { /* suppress zlib wrapper */
        wrap = 0;


        windowBits = -windowBits;
    }
#ifdef GZIP
    else if (windowBits > 15) {
        wrap = 2;       /* write gzip wrapper instead */
        windowBits -= 16;
    }







>
>







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







































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

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

    s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
    s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;










    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)
    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)
    z_streamp strm;
    const Bytef *dictionary;
    uInt  dictLength;
{
    deflate_state *s;
    uInt str, n;
    int wrap;
    unsigned avail;
    z_const unsigned char *next;

    if (deflateStateCheck(strm) || dictionary == Z_NULL)







|









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








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











|
<
<




















|
<
<
|
<







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->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.
     */

    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 = (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(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(z_streamp strm, const Bytef *dictionary,


                                 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
    strm->next_in = next;
    strm->avail_in = avail;
    s->wrap = wrap;
    return Z_OK;
}

/* ========================================================================= */
int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength)
    z_streamp strm;
    Bytef *dictionary;
    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)
    z_streamp strm;
{
    deflate_state *s;

    if (deflateStateCheck(strm)) {
        return Z_STREAM_ERROR;
    }

    strm->total_in = strm->total_out = 0;







|
<
<
|
<

















|
<
<







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(z_streamp strm, Bytef *dictionary,


                                 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(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
    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;
    strm->adler =
#ifdef GZIP
        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
#endif
        adler32(0L, Z_NULL, 0);
    s->last_flush = Z_NO_FLUSH;

    _tr_init(s);

    return Z_OK;
}

/* ========================================================================= */




int ZEXPORT deflateReset (strm)

    z_streamp strm;






{











    int ret;

    ret = deflateResetKeep(strm);
    if (ret == Z_OK)
        lm_init(strm->state);
    return ret;
}

/* ========================================================================= */
int ZEXPORT deflateSetHeader (strm, 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)
    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)
    z_streamp strm;
    int bits;
    int value;
{
    deflate_state *s;
    int put;

    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
    s = strm->state;






    if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
        return Z_BUF_ERROR;

    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)
    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) {
        /* Flush the last buffer: */
        int err = deflate(strm, Z_BLOCK);
        if (err == Z_STREAM_ERROR)
            return err;
        if (strm->avail_out == 0)
            return Z_BUF_ERROR;
    }
    if (s->level != level) {
        if (s->level == 0 && s->matches != 0) {
            if (s->matches == 1)
                slide_hash(s);
            else







|





|






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









|
<
<
<







|
<
<
<
<









|
<
<
<
<





>
>
>
>
>
>
|

>














|
<
<
<
<

















|




|







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
        INIT_STATE;
    strm->adler =
#ifdef GZIP
        s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
#endif
        adler32(0L, Z_NULL, 0);
    s->last_flush = -2;

    _tr_init(s);

    return Z_OK;
}

/* ===========================================================================
 * 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(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(z_streamp strm, unsigned *pending, int *bits) {




    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(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 ||
        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(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->last_flush != -2) {
        /* Flush the last buffer: */
        int err = deflate(strm, Z_BLOCK);
        if (err == Z_STREAM_ERROR)
            return err;
        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
        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 max_lazy;
    int nice_length;
    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
 * 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.


 *
 * 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
 * allocation.




 */
uLong ZEXPORT deflateBound(strm, sourceLen)
    z_streamp strm;
    uLong sourceLen;
{


    deflate_state *s;
    uLong complen, wraplen;



    /* conservative upper bound for compressed data */

    complen = sourceLen +
              ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;

    /* if can't get parameters, return conservative bound plus zlib wrapper */
    if (deflateStateCheck(strm))
        return complen + 6;

    /* compute wrapper length */
    s = strm->state;
    switch (s->wrap) {
    case 0:                                 /* raw deflate */
        wraplen = 0;
        break;







<
<
|
<
|
<
<












|
|
|
<
<

|
|
>
>
|
|
>
>

<
>
|
>
>
|
<
>
>
>
>

|
|
|
|
>
>
|
<
>
>

|
>
|
|

|

|







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(z_streamp strm, int good_length, int max_lazy,

                        int nice_length, 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. This
 * is an expansion of ~0.03%, plus a small constant.


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

 * 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

 * 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(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 */

    fixedlen = sourceLen + (sourceLen >> 3) + (sourceLen >> 8) +
               (sourceLen >> 9) + 4;

    /* 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 larger bound plus a zlib wrapper */
    if (deflateStateCheck(strm))
        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
        }
        break;
#endif
    default:                                /* for compiler happiness */
        wraplen = 6;
    }

    /* if not default parameters, return conservative bound */
    if (s->w_bits != 15 || s->hash_bits != 8 + 7)

        return complen + wraplen;

    /* default settings: return tight bound for that case */

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







|

>
|

|
>









|
<
<
<










|
<
<







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 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) +
               wraplen;

    /* 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(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(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
    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)
    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;







|
<
<
<







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

    /* 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) {
        /* zlib header */
        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)







>
>


|







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 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
     * 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)
    z_streamp strm;
{
    int status;

    if (deflateStateCheck(strm)) return Z_STREAM_ERROR;

    status = strm->state->status;

    /* Deallocate in reverse order of allocations: */







|
<
<







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

/* =========================================================================
 * 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)
    z_streamp dest;
    z_streamp source;
{
#ifdef MAXSEG_64K


    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;

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

    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);

    ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
    ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;




    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)
    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);
#else
    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
    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");


    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 ||
            *(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
         * 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
         * 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) &&
                 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");

        if (*scan == *match) 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;

        /* 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.
         */
        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");


        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);
#else
            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)
    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(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
     * 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.
     */
    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");

    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)
    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);
        do {
            fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
        } while (--length != 0);
        z_error("invalid match");
    }
    if (z_verbose > 1) {
        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] : \







|
<
<
<

>
>




<



















<
|










|


>
|
|
>
>
>









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










<
<
<
<
|
<
<
<




















|


|

















|
>

















|





|

|






|
|
|
|



|
|
>


|




|
|
|
|

|









|








|
>











|

|









<






|
<
<
<










|
>









|









|








|



















|
<
<
<
<

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

|
|



|







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







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(z_streamp dest, z_streamp source) {



#ifdef MAXSEG_64K
    (void)dest;
    (void)source;
    return Z_STREAM_ERROR;
#else
    deflate_state *ds;
    deflate_state *ss;



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

    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, ds->lit_bufsize * LIT_BUFS);

    ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
#ifdef LIT_MEM
    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 */
}


































































#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.
 */




local uInt longest_match(deflate_state *s, IPos cur_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);
#else
    register Bytef *strend = s->window + s->strstart + MAX_MATCH;
    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");

    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 ||
            *(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
         * 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
         * 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) &&
                 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");
        if (*scan == *match) 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;

        /* 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.
         */
        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");

        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);
#else
            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;
}


#else /* FASTEST */

/* ---------------------------------------------------------------------------
 * Optimized version for FASTEST only
 */
local uInt longest_match(deflate_state *s, IPos cur_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(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
     * 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.
     */
    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");

    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(deflate_state *s, IPos start, IPos match, int length) {




    /* check that the match is indeed a match */
    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, "(%02x %02x)", *back++, *here++);
        } while (--len != 0);
        z_error("invalid match");
    }
    if (z_verbose > 1) {
        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 */


































































































































/* ===========================================================================
 * 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
 * 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.
 */
local block_state deflate_stored(s, 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







|

|
<
<
<







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 opportunities to have a single copy from next_in to next_out.
 */
local block_state deflate_stored(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
        /* 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;

        }
        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() */


            }
            zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
            s->strstart += used;

        }
        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;
    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 (have > s->strm->avail_in)
        have = s->strm->avail_in;
    if (have) {
        read_buf(s->strm, s->window + s->strstart, have);
        s->strstart += have;

    }
    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







>








>
>



>


<














|








>
>






>







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;

    }
    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;
    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
/* ===========================================================================
 * 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)
    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
         * 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);
        }








|
<
<
<

















|







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(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
         * 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
                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]);
#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);
            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)
        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)
    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
         * 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);
        }








|










|










|










|
<
<
<


















|







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]);
#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);
            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->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(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
         * 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
        /* 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);

            _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
             * enough lookahead, the last two strings are not inserted in
             * the hash table.
             */
            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);
            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);
        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)
        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)
    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







|

|



|



|

















|
|

















|
|







|










|
<
<
<







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

            _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
             * enough lookahead, the last two strings are not inserted in
             * the hash table.
             */
            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);
            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);
        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->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(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
                         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");

        }

        /* 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);
            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)
        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)
    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);
        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)
        FLUSH_BLOCK(s, 0);
    return block_done;
}







|
>














|










|








|
<
<
<
















|









|



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");
        }

        /* 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);
            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->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(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);
        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->sym_next)
        FLUSH_BLOCK(s, 0);
    return block_done;
}

Changes to compat/zlib/deflate.h.

1
2
3
4
5
6
7
8
9
/* deflate.h -- internal compression state
 * Copyright (C) 1995-2016 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.
 */

|







1
2
3
4
5
6
7
8
9
/* deflate.h -- internal compression state
 * 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
/* 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





/* ===========================================================================
 * Internal compression state.
 */

#define LENGTH_CODES 29
/* number of length codes, not counting the special END_BLOCK code */







>
>
>
>







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




    uchf *l_buf;          /* buffer for literals or lengths */





    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







>
>
>
|
>
>
>
>







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

    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







|
|
<
<
<
<
<







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 sym_next;      /* running index in symbol buffer */
    uInt sym_end;       /* symbol table full when sym_next reaches this */






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

#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));

#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


# 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->dyn_ltree[cc].Freq++; \
    flush = (s->last_lit == s->lit_bufsize-1); \



















   }
# 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; \
    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); \
  }

#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 */







|
|
|
|
|
|
|
|



















>


|
|

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




|
>
|



|

>







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(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->sym_next] = 0; \
    s->l_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->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->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->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
[email protected]          [email protected]


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: <[email protected]>


   Jean-Loup Gailly

   EMail: <[email protected]>

   Questions about the technical content of this specification can be
   sent by email to

   Jean-Loup Gailly <[email protected]> and
   Mark Adler <[email protected]>

   Editorial comments on this specification can be sent by email to

   L. Peter Deutsch <[email protected]> and
   Glenn Randers-Pehrson <[email protected]>






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: <[email protected]>

   Questions about the technical content of this specification can be
   sent by email to:

   Jean-Loup Gailly <[email protected]> and
   Mark Adler <[email protected]>

   Editorial comments on this specification can be sent by email to:

   L. Peter Deutsch <[email protected]> and
   Glenn Randers-Pehrson <[email protected]>






























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
         <[email protected]> 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: <[email protected]>

   Questions about the technical content of this specification can be
   sent by email to:

   Jean-Loup Gailly <[email protected]> and
   Mark Adler <[email protected]>

   Editorial comments on this specification can be sent by email to:

   L. Peter Deutsch <[email protected]> and
   Glenn Randers-Pehrson <[email protected]>



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 <[email protected]>.  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
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





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

    index a zlib or gzip stream and randomly access it
    - illustrates the use of Z_BLOCK, inflatePrime(), and
      inflateSetDictionary() to provide random access







>
>
>
>










>



30
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
/* 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
 */

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


 */

/*
   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.

   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
   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
   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
   assign all portions of the remaining symbols to that code length that
   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.

   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.

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

   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
   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
   for the vast speedup.

   First, all of the possible Huffman 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
   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
   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.

   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.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.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 */
};

/* 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
   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.
   (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
   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.
 */

/* 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
   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
   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
   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.

   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[]
   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 */
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[] */
#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;












    if (done != NULL) {
        for (n = 0; n < size; n++)
            if (done[n].len)
                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
   calculation.  Uses the globals max and num. */
local big_t count(int syms, int len, int left)
{
    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 */
    if (syms == left)
        return 1;

    /* note and verify the expected state */
    assert(syms > left && left > 0 && len < max);

    /* see if we've done this one already */
    index = INDEX(syms, left, len);
    got = num[index];
    if (got)
        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;
    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);

    /* 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);
        sum += got;
        if (got == (big_t)0 - 1 || sum < got)   /* overflow */
            return (big_t)0 - 1;
    }

    /* verify that all recursive calls are productive */
    assert(sum != 0);

    /* save the result and return it */
    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. */
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;
    offset = ((offset * (offset + 1)) >> 1) + rem;
    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! */

    /* 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 */
    if (length <= offset) {
        /* if we have one already, enlarge it, zero out the appended space */

        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);
        }

        /* otherwise we need to make a new vector and zero it out */
        else {
            length = 1 << (len - root);
            while (length <= offset)
                length <<= 1;
            vector = calloc(length, sizeof(char));
        }

        /* 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;
    }

    /* set the bit */
    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
   done. */
local void examine(int syms, int len, int left, 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 */
    if (syms == left) {
        /* set the last code entry */
        code[len] = left;

        /* complete computation of memory used by this code */
        while (rem < left) {
            left -= rem;
            rem = 1 << (len - root);
            mem += rem;
        }
        assert(rem == left);



        /* 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);
        }

        /* remove entries as we drop back down in the recursion */
        code[len] = 0;
        return;
    }

    /* prune the tree if we can */
    if (beenhere(syms, len, left, 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;
    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);

    /* occupy least table spaces, creating new sub-tables as needed */
    use = least;
    while (rem < use) {
        use -= rem;
        rem = 1 << (len - root);
        mem += rem;
    }
    rem -= use;

    /* 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);
        if (rem == 0) {
            rem = 1 << (len - root);
            mem += rem;
        }
        rem--;
    }

    /* remove entries as we drop back down in the recursion */
    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)
{
    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;

    /* 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 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);

                /* 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);
            }

    /* done */
    printf("done: maximum of %d table entries\n", large);
}

/*
   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.

   To count and examine Huffman 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".

   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 */
    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;


    /* get arguments -- default to the deflate literal/length code */
    syms = 286;
    root = 9;
    max = 15;
    if (argc > 1) {
        syms = atoi(argv[1]);
        if (argc > 2) {
            root = atoi(argv[2]);
            if (argc > 3)
                max = atoi(argv[3]);
        }
    }
    if (argc > 4 || syms < 2 || root < 1 || 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;

    /* determine the number of bits in a code_t */

    for (n = 0, word = 1; word; n++, word <<= 1)

        ;

    /* make sure that the calculation of most will not overflow */
    if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (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) {
        fprintf(stderr, "%d symbols cannot be coded in %d bits\n",
                syms, max);
        return 1;
    }

    /* allocate code vector */
    code = calloc(max + 1, sizeof(int));
    if (code == NULL) {
        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 */
    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) {
            fputs("abort: unable to allocate enough memory\n", stderr);
            cleanup();
            return 1;

        }
    }

    /* count possible codes for all numbers of symbols, add up counts */
    sum = 0;
    for (n = 2; n <= syms; n++) {
        got = count(n, 1, 2);
        sum += got;
        if (got == (big_t)0 - 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);
    else
        puts(" (no length limit)");

    /* allocate and clear done array for beenhere() */
    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);
        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)))
        enough(syms);
    else
        puts("cannot handle minimum code lengths > root");

    /* done */
    cleanup();
    return 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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

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

171
172
173
174
175

176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219


220


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260

261








262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 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 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
   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
   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
   assign all portions of the remaining symbols to that code length that
   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 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 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 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
   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
   for the vast speedup.

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

   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 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
   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.
   (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 map() for the
   index, and the calculation of size in main() for the size 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 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
   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
   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
   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 been_here() for the details.

   For the deflate example of 286 symbols limited to 15-bit codes, the bit
   vectors grow to total 5.5 MB, in addition to the 4.3 MB done array itself.

 */

// Type for a variable-length, allocated string.
typedef struct {
    char *str;          // pointer to allocated string

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


// 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);
    }


    va_end(ap);


}

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

local big_t count(int syms, int left, int len) {








    // see if only one possible code
    if (syms == left)
        return 1;

    // note and verify the expected state
    assert(syms > left && left > 0 && len < g.max);

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

    // 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)
    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
    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)-1 || sum < got)      // overflow
            return (big_t)-1;
    }

    // verify that all recursive calls are productive
    assert(sum != 0);

    // 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
// as needed to allow setting the (mem,rem) bit.







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;
    int bit = 1 << (mem & 7);

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

    // 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
        char *vector;
        if (length) {
            do {
                length <<= 1;
            } while (length <= offset);
            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
        else {
            length = 16;
            while (length <= offset)
                length <<= 1;
            vector = calloc(length, 1);

            assert(vector != NULL && "out of memory");





        }

        // install the new vector
        g.done[index].len = length;
        g.done[index].vec = vector;
    }

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

local void examine(int syms, int left, int len, int mem, int rem) {





    // see if we have a complete code
    if (syms == left) {
        // set the last code entry
        g.code[len] = left;

        // complete computation of memory used by this code
        while (rem < left) {
            left -= rem;
            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, 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
        g.code[len] = 0;
        return;
    }

    // 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)
    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)
    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
    int use = least;
    while (rem < use) {
        use -= rem;
        rem = 1 << (len - g.root);
        mem += rem;
    }
    rem -= use;

    // examine codes from here, updating table space as we go
    for (use = least; use <= most; use++) {
        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 - g.root);
            mem += rem;
        }
        rem--;
    }

    // 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 codes that
// require that maximum.
local void enough(int syms) {





    // clear code
    for (int n = 0; n <= g.max; n++)
        g.code[n] = 0;

    // 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)
                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 (g.num[index - 1] && n <= left << 1)
                    examine((n - left) << 1, (n - left) << 1, g.root + 1,
                            1 << g.root, 0);
            }




    // done










    printf("maximum of %d table entries for root = %d\n", g.large, g.root);


    fputs(g.out.str, stdout);


}







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

// 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
    int syms = 286;
    g.root = 9;
    g.max = 15;
    if (argc > 1) {
        syms = atoi(argv[1]);
        if (argc > 2) {
            g.root = atoi(argv[2]);
            if (argc > 3)
                g.max = atoi(argv[3]);
        }
    }
    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 (g.max > syms - 1)
        g.max = syms - 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 (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 << g.max) - 1) {
        fprintf(stderr, "%d symbols cannot be coded in %d bits\n",
                syms, g.max);
        return 1;
    }

    // allocate code vector
    g.code = calloc(g.max + 1, sizeof(int));
    assert(g.code != NULL && "out of memory");




    // 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 {
        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));



        assert(g.num != NULL && "out of memory");
    }


    // 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;
        assert(got != (big_t)-1 && sum >= got && "overflow");



    }


    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 been_here()
    if (syms == 2)
        g.done = NULL;
    else {
        g.done = calloc(g.size, sizeof(struct tab));
        assert(g.done != NULL && "out of memory");


    }

    // 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
        fputs("cannot handle minimum code lengths > root", stderr);

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

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







|







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 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
        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 */
        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);







|







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







|







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







|







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







|




















|







29
30
31
32
33
34
35
36
37
38
39
40
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
 *                      - 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 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

    /* 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);
        *last = tmp;
        return;
    }

    /* do simple right shift by one */
    if (rot == len - 1) {
        tmp = *last;







|







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;
        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
/*
 * gzlog.c
 * Copyright (C) 2004, 2008, 2012, 2016 Mark Adler, all rights reserved
 * For conditions of distribution and use, see copyright notice in gzlog.h
 * version 2.2, 14 Aug 2012
 */

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


|

|







1
2
3
4
5
6
7
8
9
10
11
12
/*
 * gzlog.c
 * 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.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
   - 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.
   - 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







|
|







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

                log_log(log, op, ".add file read failure");
                return -1;
            }
            ret = (size_t)read(fd, data, len) != len;
            close(fd);
            if (ret) {

                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!");







>






>







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








|







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 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
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
  "http://www.w3.org/TR/REC-html40/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.  -->
</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>:
<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
|
|




|












|







1
2
3
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.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-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 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
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

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







|
>

|
<
<
<
|







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



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






</body>
</html>







|
>
>
>
>
>
>


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


/* zran.c -- example of zlib/gzip stream indexing and random access
 * Copyright (C) 2005, 2012 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
   Version 1.1  29 Sep 2012  Mark Adler */

/* Version History:
 1.0  29 May 2005  First version
 1.1  29 Sep 2012  Fix memory reallocation error








 */

/* 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.

   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.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "zlib.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 */

/* 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 */
};

/* 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 */
};

/* 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)
{
    struct point *next;

    /* if list is empty, create it (start with eight points) */
    if (index == NULL) {

        index = malloc(sizeof(struct access));
        if (index == NULL) return NULL;



        index->list = malloc(sizeof(struct point) << 3);
        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);
        if (next == NULL) {
            free_index(index);
            return NULL;
        }
        index->list = next;
    }

    /* fill in entry and increment how many we have */

    next = index->list + index->have;




    next->bits = bits;
    next->in = in;
    next->out = out;
    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 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
   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;
    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;
    unsigned char input[CHUNK];
    unsigned char window[WINSIZE];




    /* initialize inflate */
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    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 */
    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);
        if (ferror(in)) {
            ret = Z_ERRNO;
            goto build_index_error;
        }









        if (strm.avail_in == 0) {

            ret = Z_DATA_ERROR;
            goto build_index_error;

        }
        strm.next_in = input;

        /* process all of that, or until end of stream */
        do {
            /* reset sliding window if necessary */
            if (strm.avail_out == 0) {
                strm.avail_out = WINSIZE;



                strm.next_out = window;
            }





            /* inflate until out of input, output, or at end of block --

               update the total input and output counters */

            totin += strm.avail_in;
            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;
            if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)

                goto build_index_error;


            if (ret == Z_STREAM_END)
                break;





            /* 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 = realloc(index->list, sizeof(struct point) * index->have);

    index->size = index->have;


    *built = index;
    return index->size;









    /* 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
   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;
    z_stream strm;
    struct point *here;
    unsigned char input[CHUNK];
    unsigned char discard[WINSIZE];




    /* proceed only if something reasonable to do */
    if (len < 0)
        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;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;


    strm.next_in = Z_NULL;
    ret = inflateInit2(&strm, -15);         /* raw inflate */
    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) {
            ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;


            goto extract_ret;
        }
        (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits));




    }
    (void)inflateSetDictionary(&strm, here->window, WINSIZE);








    /* 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;
            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 */
            strm.avail_out = (unsigned)offset;
            strm.next_out = discard;
            offset = 0;


        }

        /* uncompress until avail_out filled, or end of stream */
        do {



            if (strm.avail_in == 0) {
                strm.avail_in = fread(input, 1, CHUNK, in);
                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;
            }
            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);

        /* if reach end of stream, then don't keep trying to get more */


        if (ret == Z_STREAM_END)
            break;

        /* 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;
}


/* 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)
{
    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");
        return 1;
    }
    in = fopen(argv[1], "rb");
    if (in == NULL) {
        fprintf(stderr, "zran: could not open %s for reading\n", argv[1]);
        return 1;
    }












    /* build index */

    len = build_index(in, SPAN, &index);
    if (len < 0) {
        fclose(in);
        switch (len) {
        case Z_MEM_ERROR:
            fprintf(stderr, "zran: out of memory\n");
            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)
        fprintf(stderr, "zran: extraction failed: %s error\n",
                len == 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);
    }

    /* clean up and exit */
    free_index(index);
    fclose(in);
    return 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
51
52
53
54
55

56
57
58
59
60
61
62

63

64
65
66







67






68



69
70
71
72
73
74
75
76
77
78
79
80


81

82
83
84
85
86
87
88
89
90
91
92
93


94
95

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

121
122
123
124
125
126
127
128
129
130
131


132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150


151
152
153
154
155

156

157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182


183
184
185
186

187
188
189
190
191
192
193
194
195
196
197
198
199
200
201

202
203
204
205
206


207
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222




223
224
225

226
227
228
229
230

231
232
233
234
235













236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290


291
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 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.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 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.
//





// 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 WINSIZE 32768U      // sliding window size
#define CHUNK 16384         // file input buffer size








// See comments in zran.h.






void deflate_index_free(struct deflate_index *index) {



    if (index != NULL) {
        free(index->list);
        free(index);
    }
}

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


                                       unsigned char *window) {

    if (index == NULL) {
        // The list is empty. Create it, starting with eight access points.
        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;
        }


    }


    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) {
            deflate_index_free(index);
            return NULL;
        }
        index->list = next;
    }

    // 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->bits = bits;
    if (left)
        memcpy(next->window, window + WINSIZE - left, left);
    if (left < WINSIZE)
        memcpy(next->window + left, window, WINSIZE - left);


    // Return the index, which may have been newly allocated or destroyed.
    return index;
}

// Decompression modes. These are the inflateInit2() windowBits parameter.
#define RAW -15
#define ZLIB 15
#define GZIP 31

// See comments in zran.h.


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


            if (strm.avail_in < sizeof(buf) && ferror(in)) {
                ret = Z_ERRNO;
                break;
            }


            if (mode == 0) {

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


            strm.data_type = 0x80;
        else {
            // Inflate and update the number of uncompressed bytes.
            unsigned before = strm.avail_out;

            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,
                              totout, strm.avail_out, win);
            if (index == NULL) {
                ret = Z_MEM_ERROR;

                break;
            }
            last = totout;
        }



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


    if (ret != Z_STREAM_END) {
        // An error was encountered. Discard the index and return a negative
        // error code.
        deflate_index_free(index);




        return ret == Z_NEED_DICT ? Z_DATA_ERROR : ret;
    }


    // 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) {

        // Seems like a realloc() to make something smaller should always work,
        // but just in case.
        deflate_index_free(index);
        return Z_MEM_ERROR;
    }













    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.

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



    // 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);
}








#else
#  define INFLATEPRIME inflatePrime
#endif

// See comments in zran.h.

ptrdiff_t deflate_index_extract(FILE *in, struct deflate_index *index,
                                off_t offset, unsigned char *buf, size_t len) {

    // Do a quick sanity check on the index.
    if (index == NULL || index->have < 1 || index->list[0].out != 0)
        return Z_STREAM_ERROR;

    // If nothing to extract, return zero bytes extracted.
    if (len == 0 || offset < 0 || offset >= index->length)
        return 0;

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

    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;

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

            // Discard up to offset uncompressed bytes.
            strm.avail_out = offset < WINSIZE ? (unsigned)offset : WINSIZE;
            strm.next_out = discard;
        }

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








            strm.next_in = input;

        }

        unsigned got = strm.avail_out;
        ret = inflate(&strm, Z_NO_FLUSH);
        got -= strm.avail_out;

        // Update the appropriate count.
        if (offset)


            offset -= got;
        else
            left -= got;

        // If we're at the end of a gzip member and there's more to read,

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


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







                    strm.avail_out = WINSIZE;
                    strm.next_out = discard;

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


            }


        }

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

#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) {







    // Open the input file.
    if (argc < 2 || argc > 3) {
        fprintf(stderr, "usage: zran file.raw [offset]\n");
        return 1;
    }
    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.
    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.
    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",
                got == Z_MEM_ERROR ? "out of memory" : "input corrupted");
    else {
        fwrite(buf, 1, got, stdout);
        fprintf(stderr, "zran: extracted %ld bytes at %lld\n", got, offset);
    }

    // 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
/* 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)
    gzFile file;
{
#ifndef NO_GZCOMPRESS
    gz_statep state;

    if (file == NULL)
        return Z_STREAM_ERROR;
    state = (gz_statep)file;











|
<
<







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(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
/* gzguts.h -- zlib internal header definitions for gz* operations
 * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 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
#  endif
#endif

#ifdef HAVE_HIDDEN
#  define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
#  define ZLIB_INTERNAL
#endif

|







|
|
<







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-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
#  undef _FILE_OFFSET_BITS
#  undef _TIME_BITS

#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
#  include <stddef.h>
#endif

#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
#  include <io.h>
#endif

#if defined(_WIN32) || defined(__CYGWIN__)
#  define WIDECHAR
#endif

#ifdef WINAPI_FAMILY
#  define open _open
#  define read _read
#  define write _write







|







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)
#  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
#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));
#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));
#endif

/* default memLevel */
#if MAX_MEM_LEVEL >= 8
#  define DEF_MEM_LEVEL 8
#else
#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL







|
|

















|
|
|
|







114
115
116
117
118
119
120
121
122
123
124
125
126
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(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(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
    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 */

        /* 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 *));
#if defined UNDER_CE
char ZLIB_INTERNAL *gz_strwinerror OF((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())
#endif







>












|

|





<
<
<
|
|
<
185
186
187
188
189
190
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(gz_statep, int, const char *);
#if defined UNDER_CE
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) */



unsigned ZLIB_INTERNAL gz_intmax(void);
#define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())

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
/* gzlib.c -- zlib functions common to reading and writing gzip files
 * Copyright (C) 2004-2017 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "gzguts.h"

#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
#  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)
     DWORD error;
{
    static char buf[1024];

    wchar_t *msgbuf;
    DWORD lasterr = GetLastError();
    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
        NULL,

|





|









<
<
<
<











|
<
<







1
2
3
4
5
6
7
8
9
10
11
12
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-2024 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "gzguts.h"

#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





#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(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
    SetLastError(lasterr);
    return buf;
}

#endif /* UNDER_CE */

/* Reset gzip file state */
local void gz_reset(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 */
    }


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







|
<
<






>
>







|
<
<
<
<







62
63
64
65
66
67
68
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(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(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
    gz_reset(state);

    /* return stream */
    return (gzFile)state;
}

/* -- see zlib.h -- */
gzFile ZEXPORT gzopen(path, mode)
    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)
    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)
    const wchar_t *path;
    const char *mode;
{
    return gz_open(path, -2, mode);
}
#endif

/* -- see zlib.h -- */
int ZEXPORT gzbuffer(file, 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 */
    state->want = size;
    return 0;
}

/* -- see zlib.h -- */
int ZEXPORT gzrewind(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)
    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;







|
|
<
>
|
>
>




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

















|
<
<
<





|
<
<
<
















|
|





|
<
<




















|
<
<
<
<







253
254
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269








270



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288



289
290
291
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(const char *path, const char *mode) {
    return gz_open(path, -1, mode);

}

/* -- see zlib.h -- */
gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
    return gz_open(path, -1, mode);
}

/* -- see zlib.h -- */








gzFile ZEXPORT gzdopen(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(const wchar_t *path, const char *mode) {



    return gz_open(path, -2, mode);
}
#endif

/* -- see zlib.h -- */
int ZEXPORT gzbuffer(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 < 8)
        size = 8;               /* needed to behave well with flushing */
    state->want = size;
    return 0;
}

/* -- see zlib.h -- */
int ZEXPORT gzrewind(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(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
    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);
        if (ret == -1)
            return -1;
        state->x.have = 0;
        state->eof = 0;
        state->past = 0;
        state->seek = 0;
        gz_error(state, Z_OK, NULL);







|







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 - (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
        state->seek = 1;
        state->skip = offset;
    }
    return state->x.pos + offset;
}

/* -- see zlib.h -- */
z_off_t ZEXPORT gzseek(file, offset, 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)
    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)
    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)
    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)
    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)
    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)
    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)
    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)







|
<
<
<
<







|
<
<














|
<
<







|
<
<




















|
<
<







|
<
<














|
<
<
<

















|
<
<







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

/* 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)
    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;
    }








|
<
<
<
<







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

#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 p, q;

    p = 1;
    do {
        q = p;
        p <<= 1;
        p++;
    } while (p > q);
    return q >> 1;
}
#endif








<




|
<
>
>
>
|
<
<






<

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


/* 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(void) {

#ifdef INT_MAX
    return INT_MAX;
#else
    unsigned p = 1, q;


    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
/* gzread.c -- zlib functions for reading gzip files
 * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 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;
    unsigned len;
    unsigned *have;
{
    int ret;
    unsigned get, max = ((unsigned)-1 >> 2) + 1;

    *have = 0;
    do {
        get = len - *have;
        if (get > max)

|





<
<
<
<
<
<
<
<
<




<
<
|
<
|
<







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-2017 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "gzguts.h"










/* 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(gz_statep state, unsigned char *buf, unsigned len,

                  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
/* 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)
    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 */







|
<
<







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(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
   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)
    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);







|
<
<







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(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
        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;
    }
    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)
    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 {







<
|
|
|
<










|
<
<







136
137
138
139
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;

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

/* 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)
    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;







|
<
<







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(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
                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)
    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 ?







|
<
<
<







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(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
    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)
    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;
        if (n > len)
            n = 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;







|
<
<
<
<


















|

|







261
262
263
264
265
266
267
268




269
270
271
272
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(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 = (unsigned)-1;
        if (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
    } while (len);

    /* return number of bytes read into user buffer */
    return got;
}

/* -- see zlib.h -- */
int ZEXPORT gzread(file, buf, 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);

    /* 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)
    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;







|
<
<
<
<




















|










|
<
<
<
<
<







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

/* -- see zlib.h -- */
#ifdef Z_PREFIX_SET
#  undef z_gzgetc
#else
#  undef gzgetc
#endif
int ZEXPORT gzgetc(file)
    gzFile file;
{
    int ret;
    unsigned char buf[1];
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return -1;
    state = (gz_statep)file;







|
<
<
<







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(gzFile file) {



    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
    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 ret < 1 ? -1 : buf[0];
}

int ZEXPORT gzgetc_(file)
gzFile file;
{
    return gzgetc(file);
}

/* -- see zlib.h -- */
int ZEXPORT gzungetc(c, file)
    int c;
    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 (serious) error */
    if (state->mode != GZ_READ ||
        (state->err != Z_OK && state->err != Z_BUF_ERROR))
        return -1;

    /* process a skip request */







|
<


|
<
<




|
<
<
<






>
>
>
>







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() */
    return gz_read(state, buf, 1) < 1 ? -1 : buf[0];

}

int ZEXPORT gzgetc_(gzFile file) {


    return gzgetc(file);
}

/* -- see zlib.h -- */
int ZEXPORT gzungetc(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
    state->x.next[0] = (unsigned char)c;
    state->x.pos--;
    state->past = 0;
    return c;
}

/* -- see zlib.h -- */
char * ZEXPORT gzgets(file, buf, 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)







|
<
<
<
<







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(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
    if (buf == str)
        return NULL;
    buf[0] = 0;
    return str;
}

/* -- see zlib.h -- */
int ZEXPORT gzdirect(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)
    gzFile file;
{
    int ret, err;
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return Z_STREAM_ERROR;
    state = (gz_statep)file;







|
<
<

















|
<
<







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(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(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
/* gzwrite.c -- zlib functions for writing gzip files
 * 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_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)
    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");

|





<
<
<
<
<
<



|
<
<







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-2019 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "gzguts.h"







/* 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(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

/* 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)
    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;







|
<
<
<







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(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
                return -1;
            }
            strm->avail_in -= (unsigned)writ;
            strm->next_in += writ;
        }
        return 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 &&







>
>
>
>
>
>
>
>
>







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
            return -1;
        }
        have -= strm->avail_out;
    } while (have);

    /* if that completed a deflate stream, allow another to start */
    if (flush == Z_FINISH)
        deflateReset(strm);

    /* 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)
    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;







|







|
<
<
<







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)
        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(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
        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)
    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 */







|
<
<
<
<







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

            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;
            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;
            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)
    gzFile file;
    voidpc buf;
    unsigned len;
{
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return 0;
    state = (gz_statep)file;








|



















|













|
<
<
<
<







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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 = (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 = (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(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
    }

    /* 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)
    voidpc 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;







|
<
<
<
|
<







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(voidpc 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;
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    }

    /* 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)
    gzFile file;
    int c;
{
    unsigned have;
    unsigned char buf[1];
    gz_statep state;
    z_streamp strm;

    /* get internal structure */
    if (file == NULL)







|
<
<
<







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(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
    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)
    gzFile file;
    const char *str;
{
    int ret;
    z_size_t len;
    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;
}

#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 len;
    unsigned left;
    char *next;
    gz_statep state;
    z_streamp strm;

    /* get internal structure */







|
<
<
<
<
|












|
>
>
>
>
|
|






|
<







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(gzFile file, const char *s) {




    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(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 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
    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);
        strm->next_in = state->in;
        strm->avail_in = left;
    }
    return len;
}

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;
{
    unsigned len, left;
    char *next;
    gz_statep state;
    z_streamp strm;

    /* get internal structure */
    if (file == NULL)







|






|
<












<
<
<
|
|
>
|
<







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;
        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, ...) {

    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(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
    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);
        strm->next_in = state->in;
        strm->avail_in = left;
    }
    return (int)len;
}

#endif

/* -- see zlib.h -- */
int ZEXPORT gzflush(file, flush)
    gzFile file;
    int flush;
{
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return Z_STREAM_ERROR;
    state = (gz_statep)file;








|









|
<
<
<







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

    /* compress remaining data with requested flush */
    (void)gz_comp(state, flush);
    return state->err;
}

/* -- see zlib.h -- */
int ZEXPORT gzsetparams(file, level, 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)
        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 */







|
<
<
<
<










|







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(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 || 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
    }
    state->level = level;
    state->strategy = strategy;
    return Z_OK;
}

/* -- see zlib.h -- */
int ZEXPORT gzclose_w(file)
    gzFile file;
{
    int ret = Z_OK;
    gz_statep state;

    /* get internal structure */
    if (file == NULL)
        return Z_STREAM_ERROR;
    state = (gz_statep)file;







|
<
<







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(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
/* infback.c -- inflate using a call-back interface
 * Copyright (C) 1995-2016 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)
z_streamp strm;
int windowBits;
unsigned char FAR *window;
const char *version;
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)

|















<
<
<







|
<
<
|
<
|
<







1
2
3
4
5
6
7
8
9
10
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-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"




/*
   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_(z_streamp strm, int windowBits,


                             unsigned char FAR *window, const char *version,

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

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







>













|
<
<







55
56
57
58
59
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(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
   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)
z_streamp strm;
in_func in;
void FAR *in_desc;
out_func out;
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 */







|
<
<
<
|
<
<







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(z_streamp strm, in_func in, void FAR *in_desc,



                        out_func out, 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
            if (ret) {
                strm->msg = (char *)"invalid distances set";
                state->mode = BAD;
                break;
            }
            Tracev((stderr, "inflate:       codes ok\n"));
            state->mode = LEN;


        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;







>







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
                do {
                    *put++ = *from++;
                } while (--copy);
            } while (state->length != 0);
            break;

        case DONE:
            /* inflate stream terminated properly -- write leftover output */
            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:                /* can't happen, but makes compilers happy */
            ret = Z_STREAM_ERROR;
            goto inf_leave;
        }

    /* Return unused input */
  inf_leave:





    strm->next_in = next;
    strm->avail_in = have;
    return ret;
}

int ZEXPORT inflateBackEnd(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;
}







|

<
<
<
<






>
|




|

>
>
>
>
>





|
<
<







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 */
            ret = Z_STREAM_END;




            goto inf_leave;

        case BAD:
            ret = Z_DATA_ERROR;
            goto inf_leave;

        default:
            /* can't happen, but makes compilers happy */
            ret = Z_STREAM_ERROR;
            goto inf_leave;
        }

    /* 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(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
      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)
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 */
    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 */







|
<
<
<



















|







43
44
45
46
47
48
49
50



51
52
53
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(z_streamp strm, unsigned start) {



    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 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
    do {
        if (bits < 15) {
            hold += (unsigned long)(*in++) << bits;
            bits += 8;
            hold += (unsigned long)(*in++) << bits;
            bits += 8;
        }
        here = lcode[hold & lmask];
      dolen:
        op = (unsigned)(here.bits);
        hold >>= op;
        bits -= op;
        op = (unsigned)(here.op);
        if (op == 0) {                          /* literal */
            Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
                    "inflate:         literal '%c'\n" :
                    "inflate:         literal 0x%02x\n", here.val));
            *out++ = (unsigned char)(here.val);
        }
        else if (op & 16) {                     /* length base */
            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];
          dodist:
            op = (unsigned)(here.bits);
            hold >>= op;
            bits -= op;
            op = (unsigned)(here.op);
            if (op & 16) {                      /* distance base */
                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;







|

|


|

|

|
|


|

















|

|


|

|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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);
      dolen:
        op = (unsigned)(here->bits);
        hold >>= op;
        bits -= op;
        op = (unsigned)(here->op);
        if (op == 0) {                          /* literal */
            Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
                    "inflate:         literal '%c'\n" :
                    "inflate:         literal 0x%02x\n", here->val));
            *out++ = (unsigned char)(here->val);
        }
        else if (op & 16) {                     /* length base */
            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);
          dodist:
            op = (unsigned)(here->bits);
            hold >>= op;
            bits -= op;
            op = (unsigned)(here->op);
            if (op & 16) {                      /* distance base */
                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
                        *out++ = *from++;
                        if (len > 1)
                            *out++ = *from++;
                    }
                }
            }
            else if ((op & 64) == 0) {          /* 2nd level distance code */
                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))];
            goto dolen;
        }
        else if (op & 32) {                     /* end-of-block */
            Tracevv((stderr, "inflate:         end of block\n"));
            state->mode = TYPE;
            break;
        }







|









|







257
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));
                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));
            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
/* 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));










|
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(z_streamp strm, unsigned start);

Changes to compat/zlib/inflate.c.

1
2
3
4
5
6
7
8
9
/* inflate.c -- zlib decompression
 * Copyright (C) 1995-2016 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/*
 * Change history:
 *
 * 1.2.beta0    24 Nov 2002

|







1
2
3
4
5
6
7
8
9
/* inflate.c -- zlib decompression
 * 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

#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)
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)
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->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)
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)
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) {


        wrap = 0;
        windowBits = -windowBits;
    }
    else {
        wrap = (windowBits >> 4) + 5;
#ifdef GUNZIP
        if (windowBits < 48)







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











|
<
<











>











|
<
<










|
<
<
<









>
>







87
88
89
90
91
92
93











94


95
96
97
98
99
100
101
102
103
104
105
106


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130


131
132
133
134
135
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












local int inflateStateCheck(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(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(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(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

    /* 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)
z_streamp strm;
int windowBits;
const char *version;
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;







|
<
<
|
<
<







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_(z_streamp strm, int windowBits,


                          const char *version, 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
    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;
{
    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
}

int ZEXPORT inflatePrime(strm, bits, value)
z_streamp strm;
int bits;
int value;
{
    struct inflate_state FAR *state;

    if (inflateStateCheck(strm)) return Z_STREAM_ERROR;


    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;







<
<
|
|
<



|
<
<
<
<



>
>







211
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_(z_streamp strm, const char *version,
                         int stream_size) {

    return inflateInit2_(strm, DEF_WBITS, version, stream_size);
}

int ZEXPORT inflatePrime(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
   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)
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) {







|
<
<







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(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
        return 0;
    }

   Then that can be linked with zlib built with MAKEFIXED defined and run:

    a.out > inffixed.h
 */
void makefixed()
{
    unsigned low, size;
    struct inflate_state state;

    fixedtables(&state);
    puts("    /* inffixed.h -- table for decoding fixed codes");
    puts("     * Generated automatically by makefixed().");







|







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

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







|
<
<
<
<







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(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
    return 0;
}

/* Macros for inflate(): */

/* check function to use adler32() for zlib or crc32() for gzip */
#ifdef GUNZIP
#  define UPDATE(check, buf, len) \
    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
#else
#  define UPDATE(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); \







|


|







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(check, buf, len) \
    (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
#else
#  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
   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)
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 */







|
<
<
<







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(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
                    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) {







<







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

            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
                state->wbits = len;
            if (len > 15 || len > state->wbits) {
                strm->msg = (char *)"invalid window size";
                state->mode = BAD;
                break;
            }
            state->dmax = 1U << len;

            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:







>







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

        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;

        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;

        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;

        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;

                        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;

        case NAME:
            if (state->flags & 0x0800) {
                if (have == 0) goto inf_leave;
                copy = 0;
                do {
                    len = (unsigned)(next[copy++]);
                    if (state->head != Z_NULL &&







>








>










>













>






|
|
>














>







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_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
                next += copy;
                if (len) goto inf_leave;
            }
            else if (state->head != Z_NULL)
                state->head->name = Z_NULL;
            state->length = 0;
            state->mode = COMMENT;

        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;

        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;







>




















>







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
            break;
#endif
        case DICTID:
            NEEDBITS(32);
            strm->adler = state->check = ZSWAP32(hold);
            INITBITS();
            state->mode = DICT;

        case DICT:
            if (state->havedict == 0) {
                RESTORE();
                return Z_NEED_DICT;
            }
            strm->adler = state->check = adler32(0L, Z_NULL, 0);
            state->mode = TYPE;

        case TYPE:
            if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;

        case TYPEDO:
            if (state->last) {
                BYTEBITS();
                state->mode = CHECK;
                break;
            }
            NEEDBITS(3);







>







>


>







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

        case COPY_:
            state->mode = COPY;

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







>


>







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
                state->mode = BAD;
                break;
            }
#endif
            Tracev((stderr, "inflate:       table sizes ok\n"));
            state->have = 0;
            state->mode = LENLENS;

        case LENLENS:
            while (state->have < state->ncode) {
                NEEDBITS(3);
                state->lens[order[state->have++]] = (unsigned short)BITS(3);
                DROPBITS(3);
            }
            while (state->have < 19)







>







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
                strm->msg = (char *)"invalid code lengths set";
                state->mode = BAD;
                break;
            }
            Tracev((stderr, "inflate:       code lengths ok\n"));
            state->have = 0;
            state->mode = CODELENS;

        case CODELENS:
            while (state->have < state->nlen + state->ndist) {
                for (;;) {
                    here = state->lencode[BITS(state->lenbits)];
                    if ((unsigned)(here.bits) <= bits) break;
                    PULLBYTE();
                }







>







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

        case LEN_:
            state->mode = LEN;

        case LEN:
            if (have >= 6 && left >= 258) {
                RESTORE();
                inflate_fast(strm, out);
                LOAD();
                if (state->mode == TYPE)
                    state->back = -1;







>


>







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
            if (here.op & 64) {
                strm->msg = (char *)"invalid literal/length code";
                state->mode = BAD;
                break;
            }
            state->extra = (unsigned)(here.op) & 15;
            state->mode = LENEXT;

        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;

        case DIST:
            for (;;) {
                here = state->distcode[BITS(state->distbits)];
                if ((unsigned)(here.bits) <= bits) break;
                PULLBYTE();
            }
            if ((here.op & 0xf0) == 0) {







>










>







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
                strm->msg = (char *)"invalid distance code";
                state->mode = BAD;
                break;
            }
            state->offset = (unsigned)here.val;
            state->extra = (unsigned)(here.op) & 15;
            state->mode = DISTEXT;

        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;

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







>
















>







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

        case LENGTH:
            if (state->wrap && state->flags) {
                NEEDBITS(32);
                if (hold != (state->total & 0xffffffffUL)) {
                    strm->msg = (char *)"incorrect length check";
                    state->mode = BAD;
                    break;
                }
                INITBITS();
                Tracev((stderr, "inflate:   length matches trailer\n"));
            }
#endif
            state->mode = DONE;

        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:

        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







|















>



|









>









>







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_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 ((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
    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);
    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)
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)
z_streamp strm;
Bytef *dictionary;
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)
z_streamp strm;
const Bytef *dictionary;
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;







|








|
<
<











|
<
<
|
<


















|
<
<
|
<







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_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(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(z_streamp strm, Bytef *dictionary,


                                 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(z_streamp strm, const Bytef *dictionary,


                                 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
        return Z_MEM_ERROR;
    }
    state->havedict = 1;
    Tracev((stderr, "inflate:   dictionary set\n"));
    return Z_OK;
}

int ZEXPORT inflateGetHeader(strm, 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;








|
<
<
<







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(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
   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)
unsigned FAR *have;
const unsigned char FAR *buf;
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)
z_streamp strm;
{
    unsigned len;               /* number of bytes to look at or looked at */

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





    in = strm->total_in;  out = strm->total_out;
    inflateReset(strm);
    strm->total_in = in;  strm->total_out = out;

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







|
<
<
|
<


















|
<
<

>












|



















>
>
>
>
>



>












|
<
<







|
<
<
<







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(unsigned FAR *have, const unsigned char FAR *buf,


                          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(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->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(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(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
        zmemcpy(window, state->window, wsize);
    }
    copy->window = window;
    dest->state = (struct internal_state FAR *)copy;
    return Z_OK;
}

int ZEXPORT inflateUndermine(strm, 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)
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)
        state->wrap |= 4;
    else
        state->wrap &= ~4;
    return Z_OK;
}

long ZEXPORT inflateMark(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)
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);
}







|
<
<
<














|
<
<
<




|






|
<
<










|
<
<





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(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(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 && state->wrap)
        state->wrap |= 4;
    else
        state->wrap &= ~4;
    return Z_OK;
}

long ZEXPORT inflateMark(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(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
/* inflate.h -- internal inflate state definition
 * Copyright (C) 1995-2016 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.
 */

|







1
2
3
4
5
6
7
8
9
/* inflate.h -- internal inflate state definition
 * 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
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) */

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







|
>







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, 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
/* inftrees.c -- generate Huffman trees for efficient decoding
 * Copyright (C) 1995-2017 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 ";
/*
  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;
code FAR * FAR *table;
unsigned FAR *bits;
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 */

|









|



















<
<
|
|
<
|
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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-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.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(codetype type, unsigned short FAR *lens,
                                unsigned codes, code FAR * FAR *table,

                                unsigned FAR *bits, 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
    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};
    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,







|







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, 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
    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
   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
   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));







|


|
|














|
|
|
34
35
36
37
38
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 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 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(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
$!------------------------------------------------------------------------------
$! 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
$!               subdir path, update module search in makefile.in
$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly 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







|

|







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 examples
$!               subdir path, update module search in makefile.in
$! 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
    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
(last 4 bytes)
        Close #1
    Else
        MsgBox "Compression error"
    End If
    Erase bytaryCpr
    Erase bytaryOri







|







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 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
        ZLIB version 1.2.11 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,
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')

|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
        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 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
                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.

        Mainly for the reason above, always open zipped files in binary mode.







|


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 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
  EXPORT SYMBOL("crc32_z")
  EXPORT SYMBOL("deflateGetDictionary")
  EXPORT SYMBOL("gzfread")
  EXPORT SYMBOL("gzfwrite")
  EXPORT SYMBOL("inflateCodesUsed")
  EXPORT SYMBOL("inflateValidate")
  EXPORT SYMBOL("uncompress2")









ENDPGMEXP







>
>
>
>
>
>
>
>


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
      *  ZLIB.INC - Interface to the general purpose compression library
      *
      *  ILE RPG400 version by Patrick Monnerat, DATASPHERE.
      *  Version 1.2.11
      *
      *
      *  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_VERNUM     C                   X'12a0'
     D ZLIB_VER_MAJOR  C                   1
     D ZLIB_VER_MINOR  C                   2
     D ZLIB_VER_REVISION...
     D                 C                   11
     D ZLIB_VER_SUBREVISION...
     D                 C                   0
      *
      *  Other equates.
      *
     D Z_NO_FLUSH      C                   0
     D Z_PARTIAL_FLUSH...



|




















|


|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
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.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.3.1'
     D ZLIB_VERNUM     C                   X'12a0'
     D ZLIB_VER_MAJOR  C                   1
     D ZLIB_VER_MINOR  C                   3
     D ZLIB_VER_REVISION...
     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
      <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:Files>

      <QPG:PackageFilter>
         <QPM:PackageManifest>
            <QPM:PackageDescription>
               <QPM:PackageType>Library</QPM:PackageType>
               <QPM:PackageReleaseNotes></QPM:PackageReleaseNotes>







|
|
|
|







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







|







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.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
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)
    void *q;
    unsigned n, m;
{
    (void)q;
    return calloc(n, m);
}

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)
    Byte *compr, *uncompr;
    uLong comprLen, 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");








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


<
<
<
|
<
<
<




|
<












<
<
<
<
<



|
<
|
<







29
30
31
32
33
34
35
36
















37
38



39



40
41
42
43
44

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

















#ifdef Z_SOLO




static void *myalloc(void *q, unsigned n, unsigned m) {



    (void)q;
    return calloc(n, m);
}

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;






/* ===========================================================================
 * Test compress() and uncompress()
 */
static void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,

                   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
        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;
{
#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;







<
<
<
|
<







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



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
}

#endif /* Z_SOLO */

/* ===========================================================================
 * Test deflate() with small buffers
 */
void test_deflate(compr, 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;







|
<
<
<







159
160
161
162
163
164
165
166



167
168
169
170
171
172
173
}

#endif /* Z_SOLO */

/* ===========================================================================
 * Test deflate() with small buffers
 */
static void test_deflate(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
    err = deflateEnd(&c_stream);
    CHECK_ERR(err, "deflateEnd");
}

/* ===========================================================================
 * Test inflate() with small buffers
 */
void test_inflate(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = zalloc;
    d_stream.zfree = zfree;







|
<
|
<







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
 */
static void test_inflate(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;
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
        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)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    z_stream c_stream; /* compression stream */
    int err;

    c_stream.zalloc = zalloc;
    c_stream.zfree = zfree;
    c_stream.opaque = (voidpf)0;








|
<
|
<







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
 */
static void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,

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







|







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)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
    err = deflateEnd(&c_stream);
    CHECK_ERR(err, "deflateEnd");
}

/* ===========================================================================
 * Test inflate() with large buffers
 */
void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = zalloc;
    d_stream.zfree = zfree;







|
<
|
<







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
 */
static void test_large_inflate(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;
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
        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) {
        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;
{
    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;







|










<
<
|
<







314
315
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 + 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
 */


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

    *comprLen = c_stream.total_out;
}

/* ===========================================================================
 * Test inflateSync()
 */
void test_sync(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = zalloc;
    d_stream.zfree = zfree;







<
|
|
<







360
361
362
363
364
365
366

367
368

369
370
371
372
373
374
375

    *comprLen = c_stream.total_out;
}

/* ===========================================================================
 * Test inflateSync()
 */

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
    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");
        /* 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)
    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;








|
|
<











|
<
<
<







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_STREAM_END) {
        fprintf(stderr, "inflate should report Z_STREAM_END\n");

        exit(1);
    }
    err = inflateEnd(&d_stream);
    CHECK_ERR(err, "inflateEnd");

    printf("after inflateSync(): hel%s\n", (char *)uncompr);
}

/* ===========================================================================
 * Test deflate() with preset dictionary
 */
static void test_dict_deflate(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
    err = deflateEnd(&c_stream);
    CHECK_ERR(err, "deflateEnd");
}

/* ===========================================================================
 * Test inflate() with a preset dictionary
 */
void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
    Byte *compr, *uncompr;
    uLong comprLen, uncomprLen;
{
    int err;
    z_stream d_stream; /* decompression stream */

    strcpy((char*)uncompr, "garbage");

    d_stream.zalloc = zalloc;
    d_stream.zfree = zfree;







|
<
|
<







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
 */
static void test_dict_inflate(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;
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
    }
}

/* ===========================================================================
 * Usage:  example [output.gz  [input.gz]]
 */

int main(argc, argv)
    int argc;
    char *argv[];
{
    Byte *compr, *uncompr;
    uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
    uLong uncomprLen = comprLen;

    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");

    }

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







<
<
|
<

<
|
>







|
>







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(int argc, char *argv[]) {

    Byte *compr, *uncompr;

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

    test_dict_deflate(compr, comprLen);
    test_dict_inflate(compr, comprLen, uncompr, uncomprLen);

    free(compr);
    free(uncompr);

    return 0;
}







|









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 = 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
    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));
                                                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);







|







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, "!", (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
    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)
{

    buf += 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;







>
|







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;
    (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
#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 *));
#endif
#endif

#if defined(UNDER_CE)
#  include <windows.h>
#  define perror(s) pwinerror(s)








|







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(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
#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)
    void *q;
    unsigned n, m;
{
    (void)q;
    return calloc(n, m);
}

void myfree(q, 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;
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;







<
<
<
|
<
<
<




|
<
<












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







145
146
147
148
149
150
151



152



153
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




static void *myalloc(void *q, unsigned n, unsigned m) {



    (void)q;
    return calloc(n, m);
}

static void myfree(void *q, void *p) {


    (void)q;
    free(p);
}

typedef struct gzFile_s {
    FILE *file;
    int write;
    int err;
    char *msg;
    z_stream strm;
} *gzFile;






static gzFile gz_open(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
        return NULL;
    }
    gz->err = 0;
    gz->msg = "";
    return gz;
}

int gzwrite OF((gzFile, const void *, unsigned));


int gzwrite(gz, buf, len)
    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;
{
    int ret;
    unsigned got;
    unsigned char in[1];
    z_stream *strm;

    if (gz == NULL || gz->write)
        return 0;







|
>
|
|
|
<
|
>
|
>

















<
<
<
<
<
|
<







197
198
199
200
201
202
203
204
205
206
207
208

209
210
211
212
213
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;
}

static gzFile gzopen(const char *path, const char *mode) {
    return gz_open(path, -1, mode);
}

static gzFile gzdopen(int fd, const char *mode) {

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






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
        }
        if (ret == Z_STREAM_END)
            inflateReset(strm);
    } while (strm->avail_out);
    return len - strm->avail_out;
}

int gzclose OF((gzFile));

int gzclose(gz)
    gzFile gz;
{
    z_stream *strm;
    unsigned char out[BUFLEN];

    if (gz == NULL)
        return Z_STREAM_ERROR;
    strm = &(gz->strm);
    if (gz->write) {







<
<
|
<
<







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



static int gzclose(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
    else
        inflateEnd(strm);
    fclose(gz->file);
    free(gz);
    return Z_OK;
}

const char *gzerror OF((gzFile, int *));

const char *gzerror(gz, 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;
{
    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 <[email protected]> */

/* Try compressing the input file at once using mmap. Return Z_OK if
 * if success, Z_ERRNO otherwise.
 */
int gz_compress_mmap(in, 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;








<
<
|
<
<
<








<
<
<
<
<
<
<
<
<
<



<
|
<




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



|

|
<
<
<







279
280
281
282
283
284
285


286



287
288
289
290
291
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;
}



static const char *gzerror(gzFile gz, int *err) {



    *err = gz->err;
    return gz->msg;
}

#endif

static char *prog;











/* ===========================================================================
 * Display error message and exit
 */

static void error(const char *msg) {

    fprintf(stderr, "%s: %s\n", prog, msg);
    exit(1);
}

































#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <[email protected]> */

/* Try compressing the input file at once using mmap. Return Z_OK if
 * success, Z_ERRNO otherwise.
 */
static int gz_compress_mmap(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

    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.
 */
void gz_uncompress(in, out)




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









|

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







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

/* ===========================================================================
 * Compress input to output then close both files.
 */

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
}


/* ===========================================================================
 * Compress the given file: create a corresponding .gz file and remove the
 * original.
 */
void file_compress(file, 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);







|
<
<
<







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.
 */
static void file_compress(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
    unlink(file);
}


/* ===========================================================================
 * Uncompress the given file and remove the original.
 */
void file_uncompress(file)
    char  *file;
{
    local char buf[MAX_NAME_LEN];
    char *infile, *outfile;
    FILE  *out;
    gzFile in;
    unsigned 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)







|
<
<




|







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.
 */
static void file_uncompress(char *file) {


    local char buf[MAX_NAME_LEN];
    char *infile, *outfile;
    FILE  *out;
    gzFile in;
    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
 *   -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 copyout = 0;
    int uncompr = 0;
    gzFile file;
    char *bname, outmode[20];

#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    snprintf(outmode, sizeof(outmode), "%s", "wb6 ");







<
<
|
<







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(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
<?xml version="1.0" ?>
<package name="zlib" version="1.2.11">
    <library name="zlib" dlversion="1.2.11" 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" />

|
|







1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" ?>
<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
/* trees.c -- output deflated data using Huffman coding
 * Copyright (C) 1995-2017 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
 *

|







1
2
3
4
5
6
7
8
9
/* trees.c -- output deflated data using Huffman coding
 * 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
    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 */
};







local const static_tree_desc  static_l_desc =
{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};

local const static_tree_desc  static_d_desc =
{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};

local const static_tree_desc  static_bl_desc =
{(const ct_data *)0, extra_blbits, 0,   BL_CODES, MAX_BL_BITS};

/* ===========================================================================







 * Local (static) routines in this file.




















































 */







local void tr_static_init OF((void));
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));
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));
local void compress_block OF((deflate_state *s, const ct_data *ltree,
                              const ct_data *dtree));
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));
local void bi_flush       OF((deflate_state *s));





#ifdef GEN_TREES_H
local void gen_trees_header OF((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(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))
     * 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;







>
>
>
>
>
>
|


|


|



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

>
>
>
>
>

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

|












<
<
<
<
<
<
<
<
<





|
<
<
<
<
<
<





|







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209



210
211
212
213
214
215
216
217
218
219
220
221
222



223

224

225
226
227

228
229
230
231
232
233
234
235
236
237
238
239
240
241
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 TCONST static_tree_desc static_l_desc =
{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};

local TCONST static_tree_desc static_d_desc =
{static_dtree, extra_dbits, 0,          D_CODES, MAX_BITS};

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)); \
}

/* ===========================================================================
 * 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
     * 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));

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


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










/* ===========================================================================
 * 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(deflate_state *s, int value, int length) {






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


/* the arguments must not have side effects */

/* ===========================================================================
 * Initialize the various 'constant' tables.
 */
local void tr_static_init()
{
#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 */







|
<







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(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
    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++) {
            _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;

    /* 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++) {
            _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++) {
            _dist_code[256 + dist++] = (uch)code;
        }
    }
    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]++;







|








|





|







|



|







313
314
315
316
317
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++) {
            _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;

    /* 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++) {
            _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++) {
            _dist_code[256 + dist++] = (uch)code;
        }
    }
    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
#  ifdef GEN_TREES_H
    gen_trees_header();
#  endif
#endif /* defined(GEN_TREES_H) || !defined(STDC) */
}

/* ===========================================================================
 * Genererate 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" : ", "))

void gen_trees_header()
{
    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");








|








|

|
<







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) */
}

/* ===========================================================================
 * 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" : ", "))

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
        fprintf(header, "%5u%s", base_dist[i],
                SEPARATOR(i, D_CODES-1, 10));
    }

    fclose(header);
}
#endif /* GEN_TREES_H */

















/* ===========================================================================
 * Initialize the tree data structures for a new zlib stream.
 */
void ZLIB_INTERNAL _tr_init(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;







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




|
<
<







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







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







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);
}



















#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

/* ===========================================================================
 * 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)
    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)) {
            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;







|
<
<
<
<





|







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(deflate_state *s, ct_data *tree, int k) {




    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)) {
            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
 * 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)
    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++) {
        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];
        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;
        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[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);








|
<
<
<




















|










|











|

|
|







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(deflate_state *s, tree_desc *desc) {



    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++) {
        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];
        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;
        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[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
                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 */

    /* 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));

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

        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)
    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[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;







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









|
<
<
<








|







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


















#ifdef DUMP_BL_TREE













#  include <stdio.h>





#endif





/* ===========================================================================
 * 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(deflate_state *s, tree_desc *desc) {



    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[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
        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,
     * 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.
     */







|







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,
     * 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
    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)
    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 */

    for (n = 0; n <= max_code; n++) {
        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++;







|
<
<
<
<









|


|







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(deflate_state *s, ct_data *tree, int max_code) {




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

    for (n = 0; n <= max_code; n++) {
        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
    }
}

/* ===========================================================================
 * Send a literal or distance tree in compressed form, using the codes in
 * bl_tree.
 */
local void send_tree (s, tree, 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 */
    if (nextlen == 0) max_count = 138, min_count = 3;

    for (n = 0; n <= max_code; n++) {
        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);

        } else if (count <= 10) {
            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);
        }
        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)
    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.
     */

    /* 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;
    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)
    deflate_state *s;
    int lcodes, dcodes, blcodes; /* number of codes for each tree */
{
    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 */
    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 */
    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));

    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)
    deflate_state *s;
    charf *buf;       /* input block */
    ulg stored_len;   /* length of input block */
    int last;         /* one if this is the last block for a file */
{
    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);

    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;
#endif
}

/* ===========================================================================
 * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
 */
void ZLIB_INTERNAL _tr_flush_bits(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)
    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);
}

































































































/* ===========================================================================
 * 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)
    deflate_state *s;
    charf *buf;       /* input block, or NULL if too old */
    ulg stored_len;   /* length of input block */
    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 */







|
<
<
<
<








|



|










|


|


|
















|
<
<








|
|










|











|
<
|
<






|
|
|






|


|






|
<
<
|
<
<
|



>
|





|






|
<
<







|
<
<







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





|
<
<
|
<
<







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(deflate_state *s, ct_data *tree, int max_code) {




    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 */
    if (nextlen == 0) max_count = 138, min_count = 3;

    for (n = 0; n <= max_code; n++) {
        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);

        } else if (count <= 10) {
            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);
        }
        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(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.
     */

    /* 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;
    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(deflate_state *s, int lcodes, int dcodes,

                          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 */
    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 */
    Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));

    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(deflate_state *s, charf *buf,


                                    ulg stored_len, int last) {


    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);
    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;
#endif
}

/* ===========================================================================
 * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
 */
void ZLIB_INTERNAL _tr_flush_bits(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(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(deflate_state *s, charf *buf,


                                   ulg stored_len, int last) {


    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

        /* 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;

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


        if (static_lenb <= opt_lenb) 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) {
                       /* 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
    } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
#endif
        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);
        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));
}

/* ===========================================================================
 * 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;
    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;





    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_dtree[d_code(dist)].Freq++;
    }

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







|
|



|

>
|
>
>









|










<
|
<
<
<
|






|
|
|


















|
|






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











|


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

        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->sym_next / 3));

#ifndef FORCE_STATIC
        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) {
                       /* 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);


    } else if (static_lenb == opt_lenb) {



        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);
        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));
}

/* ===========================================================================
 * Save the match info and tally the frequency counts. Return true if
 * the current block must be flushed.
 */
int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
#ifdef LIT_MEM



    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_dtree[d_code(dist)].Freq++;
    }
    return (s->sym_next == s->sym_end);










}





























































































































































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







<
<
<
|
|
<







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(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
    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;
{
    return uncompress2(dest, destLen, source, &sourceLen);
}







<
<
<
|
|
<


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

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





|







|


<
<
<
<







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 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 common build of zlib as a DLL.
    (Please remark the character '1' in the name.)





    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
    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 <[email protected]>







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




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.













**

This document is written and maintained by
Cosmin Truta <[email protected]>

Changes to compat/zlib/win32/Makefile.bor.

1
2
3
4
5
6
7
8
9
10
11
12
13
# 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)





<







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


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













<
<
<
<







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







<







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






<
<
<
<







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)





# 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
ZLIB DATA COMPRESSION LIBRARY

zlib 1.2.11 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 [email protected]).  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 <[email protected]>.  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.


Manifest:

The package zlib-1.2.11-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)


|















|
|




|







1
2
3
4
5
6
7
8
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.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 [email protected]).  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 <[email protected]>.  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 zlib FAQ http://zlib.net/zlib_faq.html before
asking for help.


Manifest:

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

What's here
===========
  The official ZLIB1.DLL


Source
======
  zlib version 1.2.11
  available at http://www.gzip.org/zlib/


Specification and rationale
===========================
  See the accompanying DLL_FAQ.txt









|







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.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
; large file functions
    gzopen64
    gzseek64
    gztell64
    gzoffset64
    adler32_combine64
    crc32_combine64

; checksum functions
    adler32
    adler32_z
    crc32
    crc32_z
    adler32_combine
    crc32_combine


; various hacks, don't look :)
    deflateInit_
    deflateInit2_
    inflateInit_
    inflateInit2_
    inflateBackInit_
    gzgetc_







>







>
>







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







|







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-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
/* zconf.h -- configuration of the zlib compression library
 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* @(#) $Id$ */

#ifndef ZCONF_H
#define ZCONF_H

|







1
2
3
4
5
6
7
8
9
/* zconf.h -- configuration of the zlib compression library
 * 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
#    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_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







>
>
>







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
#if defined(ZLIB_CONST) && !defined(z_const)
#  define z_const const
#else
#  define z_const
#endif

#ifdef Z_SOLO



   typedef unsigned long z_size_t;

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







>
>
>
|
>







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







<
<
<
<
<
<
<
<







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









/* 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
    * define ZLIB_WINAPI.
    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
    */
#  ifdef ZLIB_WINAPI
#    ifdef FAR
#      undef FAR
#    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







>
>
>







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

#endif





#ifndef Z_SOLO
#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
#    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







|
>
|
>

>
>
>
>
>

|







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

#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)
#    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
#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)
#    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 */







|







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__)
#    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
/* zconf.h -- configuration of the zlib compression library
 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* @(#) $Id$ */

#ifndef ZCONF_H
#define ZCONF_H

|







1
2
3
4
5
6
7
8
9
/* zconf.h -- configuration of the zlib compression library
 * 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
#    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_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







>
>
>







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
#if defined(ZLIB_CONST) && !defined(z_const)
#  define z_const const
#else
#  define z_const
#endif

#ifdef Z_SOLO



   typedef unsigned long z_size_t;

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







>
>
>
|
>







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







<
<
<
<
<
<
<
<







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









/* 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
    * define ZLIB_WINAPI.
    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
    */
#  ifdef ZLIB_WINAPI
#    ifdef FAR
#      undef FAR
#    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







>
>
>







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

#endif





#ifndef Z_SOLO
#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
#    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







|
>
|
>

>
>
>
>
>

|







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

#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)
#    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
#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)
#    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 */







|







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__)
#    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
/* zconf.h -- configuration of the zlib compression library
 * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

/* @(#) $Id$ */

#ifndef ZCONF_H
#define ZCONF_H

|







1
2
3
4
5
6
7
8
9
/* zconf.h -- configuration of the zlib compression library
 * 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
#    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_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







>
>
>







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
#if defined(ZLIB_CONST) && !defined(z_const)
#  define z_const const
#else
#  define z_const
#endif

#ifdef Z_SOLO



   typedef unsigned long z_size_t;

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







>
>
>
|
>







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







<
<
<
<
<
<
<
<







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









/* 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
    * define ZLIB_WINAPI.
    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
    */
#  ifdef ZLIB_WINAPI
#    ifdef FAR
#      undef FAR
#    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







>
>
>







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

#endif





#ifndef Z_SOLO
#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
#    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







|
>
|
>

>
>
>
>
>

|







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

#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)
#    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
#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)
#    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 */







|







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__)
#    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
.TH ZLIB 3 "15 Jan 2017"
.SH NAME
zlib \- compression/decompression library
.SH SYNOPSIS
[see
.I zlib.h
for full description]
.SH DESCRIPTION
|







1
2
3
4
5
6
7
8
.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
.IP
http://zlib.net/zlib_faq.html
.LP
before asking for help.
Send questions and/or comments to [email protected],
or (for the Windows DLL version) to Gilles Vollant ([email protected]).
.SH AUTHORS AND LICENSE
Version 1.2.11
.LP
Copyright (C) 1995-2017 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







|

|







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 [email protected],
or (for the Windows DLL version) to Gilles Vollant ([email protected]).
.SH AUTHORS AND LICENSE
Version 1.3.1
.LP
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
/* zlib.h -- interface of the 'zlib' general purpose compression library
  version 1.2.11, January 15th, 2017

  Copyright (C) 1995-2017 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

|

|







1
2
3
4
5
6
7
8
9
10
11
/* zlib.h -- interface of the 'zlib' general purpose compression library
  version 1.3.1, January 22nd, 2024

  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

#include "zconf.h"

#ifdef __cplusplus
extern "C" {
#endif

#define ZLIB_VERSION "1.2.11"
#define ZLIB_VERNUM 0x12b0
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
#define ZLIB_VER_REVISION 11
#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







|
|

|
|







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.3.1"
#define ZLIB_VERNUM 0x1310
#define ZLIB_VER_MAJOR 1
#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
  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));

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







|
|







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

#define zlib_version zlibVersion()
/* for compatibility with versions < 1.0.2 */


                        /* basic functions */

ZEXTERN const char * ZEXPORT zlibVersion OF((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));

     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.

     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));
/*
    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







|







|




|
















|







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
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(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(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.  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(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
  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
  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







|







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

    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







|
|







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 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
  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));
/*
     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));

     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.


     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));
/*
    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







|














|







|
>













|







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(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(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.  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(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
  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));
/*
     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));

     This is another version of deflateInit with more compression options.  The
   fields next_in, zalloc, zfree and opaque must be initialized before by the
   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







|

















|
|
|
|
|
|


|
<







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(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(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 zalloc, zfree and opaque must be initialized before by the 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
   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));
/*
     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







|
|
|







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(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
     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));
/*
     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.

     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));
/*
     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));
/*
     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.

     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));
/*
     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().


     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().

     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));
/*
     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));
/*
     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));
/*
     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));
/*
     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));
/*
     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().


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

     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







|
|
|






|












|
|
















|




|





|
|
|






|
|
|
|
|
>












|










|
|
|
|
|












|
|













|
|
|












|
|
|














|
|















|
|
>






|
|







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



     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));
/*
     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));
/*
     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.

     inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
   stream state is inconsistent.
*/

ZEXTERN int ZEXPORT inflateSync OF((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.
*/

ZEXTERN int ZEXPORT inflateCopy OF((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));
/*
     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.


     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));
/*
     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));
/*
     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));
/*
     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







|
|
|
>
>













|
|
|




















|
|
|






|





|












|
|
|
|


|
|














|




>





|
|












|
|
|


















|







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 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(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(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.
   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(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 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(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(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(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(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(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
   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));
/*
     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







|
|







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(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
   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));

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

ZEXTERN int ZEXPORT inflateBack OF((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







|
|



















|
|
|

|
|
|







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(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)(void FAR *,
                            z_const unsigned char FAR * FAR *);
typedef int (*out_func)(void FAR *, unsigned char FAR *, unsigned);

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
   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));
/*
     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));
/* 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







|







|







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(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(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
     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));
/*
     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));
/*
     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));
/*
     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));
/*
     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));
/*
     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));


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







|
|













|
|
|













|






|
|
















|
|


















|

>
|
|
|
|
|
|
|
<







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(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(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(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(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(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(const char *path, const char *mode);

     Open the gzip (.gz) file at path for reading and decompressing, or
   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.


     "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
     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));
/*
     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.

     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));
/*
     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).

     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));
/*
     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.

     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));
/*
     Reads the given number of uncompressed bytes from the compressed file.  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,







|

|
|
|


















|

|
|
|
|
|
|
|







|

|
|
|






|

|







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(int fd, const char *mode);
/*
     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(gzFile file, unsigned size);
/*
     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(gzFile file, int level, int strategy);
/*
     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(gzFile file, voidp buf, unsigned len);
/*
     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

     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));
/*
     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.

     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
   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.
*/

ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
                                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
   error.
*/

ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
                                      z_size_t nitems, gzFile file));
/*
     gzfwrite() writes 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, ...));
/*
     Converts, formats, and writes the arguments to the compressed file under
   control of the format string, 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()
   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));
/*
     Writes the given null-terminated string to the compressed 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));
/*
     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.

     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));
/*
     Writes c, converted to an unsigned char, into the compressed file.  gzputc
   returns the value that was written, or -1 in case of error.
*/

ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
/*
     Reads one byte from the compressed 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));
/*
     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.
   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));
/*
     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.

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

     Sets the starting position for the next gzread or gzwrite on the given
   compressed 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));
/*
     Rewinds the given file. This function is supported only for reading.

     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
*/

/*
ZEXTERN z_off_t ZEXPORT    gztell OF((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().

     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
*/

/*
ZEXTERN z_off_t ZEXPORT gzoffset OF((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.
*/

ZEXTERN int ZEXPORT gzeof OF((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.

     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));
/*
     Returns 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));
/*
     Flushes all pending output if necessary, closes the compressed file and
   deallocates 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));
/*
     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));
/*
     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.

     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));
/*
     Clears 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));
/*
     Update a running Adler-32 checksum with the bytes buf[0..len-1] and

   return the updated checksum.  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));
/*
     Same as adler32(), but with a size_t length.
*/

/*
ZEXTERN uLong ZEXPORT adler32_combine OF((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));
/*
     Update a running CRC-32 with the bytes buf[0..len-1] and return the

   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.

   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));
/*
     Same as crc32(), but with a size_t length.
*/

/*
ZEXTERN uLong ZEXPORT crc32_combine OF((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.












*/


                        /* 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));
#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),\







|
|

|
|
|
|
|










|




|


|
<

|
|
<


|
|

|










|

|
|






|




|

|





|

|
|
|
|
>
|






|

|



|

|






|

|
|








|

|
|
|











|
|

|
|














|

|

|



|

|
|
|
|





|

|
|
|
|
|


|

|
|
|
|
|
|
|






|

|


















|

|
|









|
|










|

|
|
|
|










|

|














|


>
|
|














|
|





|
|









|


>
|
|
|











|
|





|





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








|
|
|
|
|
|
|
|
|
|
|
|
|
|







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(voidp buf, z_size_t size, z_size_t nitems,
                                 gzFile file);
/*
     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 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, resetting and retrying on end-of-file, when size is not 1.
*/

ZEXTERN int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len);

/*
     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.

*/

ZEXTERN z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size,
                                  z_size_t nitems, gzFile file);
/*
     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(gzFile file, const char *format, ...);
/*
     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(),
   because the secure snprintf() or vsnprintf() functions were not available.
   This can be determined using zlibCompileFlags().
*/

ZEXTERN int ZEXPORT gzputs(gzFile file, const char *s);
/*
     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(gzFile file, char *buf, int len);
/*
     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(gzFile file, int c);
/*
     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(gzFile file);
/*
     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(int c, gzFile file);
/*
     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(gzFile file, int flush);
/*
     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(gzFile file,
                               z_off_t offset, int whence);

     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(gzFile file);
/*
     Rewind file. This function is supported only for reading.

     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
*/

/*
ZEXTERN z_off_t ZEXPORT    gztell(gzFile file);

     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(gzFile file);

     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(gzFile file);
/*
     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(gzFile file);
/*
     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(gzFile file);
/*
     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(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(gzFile file, int *errnum);
/*
     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(gzFile file);
/*
     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(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
   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(uLong adler, const Bytef *buf,
                                z_size_t len);
/*
     Same as adler32(), but with a size_t length.
*/

/*
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(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.
   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(uLong crc, const Bytef *buf,
                              z_size_t len);
/*
     Same as crc32(), but with a size_t length.
*/

/*
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.
*/

/*
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_(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
 * 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 */
#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));
#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

#  else
#    define gzopen gzopen64
#    define gzseek gzseek64
#    define gztell gztell64
#    define gzoffset gzoffset64
#    define adler32_combine adler32_combine64
#    define crc32_combine crc32_combine64

#  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));
#  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));
#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));

#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));
#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));
#  endif
#endif

#ifdef __cplusplus
}
#endif

#endif /* ZLIB_H */







|
















|
|
|
|
|
>
|










>







>


|
|
|
|
|
>
|


|
|
|
|
|
>
|




|
>
|




|
|
|
|
|
|
|
|
|
|
|



|
|
|








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






    uncompress2;
    gzfread;
    gzfwrite;
    deflateGetDictionary;
    adler32_z;
    crc32_z;
} ZLIB_1.2.7.1;













>
>
>
>
>
>
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
    (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()
{
    return ZLIB_VERSION;
}

uLong ZEXPORT zlibCompileFlags()
{
    uLong flags;

    flags = 0;
    switch ((int)(sizeof(uInt))) {
    case 2:     break;
    case 4:     flags += 1;     break;
    case 8:     flags += 2;     break;







|
<



|
<







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(void) {

    return ZLIB_VERSION;
}

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







>



>







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
#ifdef ZLIB_DEBUG
#include <stdlib.h>
#  ifndef verbose
#    define verbose 0
#  endif
int ZLIB_INTERNAL z_verbose = verbose;

void ZLIB_INTERNAL z_error (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)
    int err;
{
    return ERR_MSG(err);
}

#if defined(_WIN32_WCE)
    /* The 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)
    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)
    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)
    Bytef* dest;
    uInt  len;
{
    if (len == 0) return;
    do {
        *dest++ = 0;  /* ??? to be unrolled */
    } while (--len != 0);
}
#endif








|
<
<








|
<
<



|
|








|
<
<
<
<






|
<
<
<
<








|
<
<
<







115
116
117
118
119
120
121
122


123
124
125
126
127
128
129
130
131


132
133
134
135
136
137
138
139
140
141
142
143
144
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(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(int err) {


    return ERR_MSG(err);
}

#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(Bytef* dest, const Bytef* source, uInt len) {




    if (len == 0) return;
    do {
        *dest++ = *source++; /* ??? to be unrolled */
    } while (--len != 0);
}

int ZLIB_INTERNAL zmemcmp(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(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
/* 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 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.







|
<







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 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
    /* 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)
{
    int n;

    (void)opaque;

    if (*(ush*)&ptr != 0) { /* object < 64K */
        farfree(ptr);
        return;







|
<







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

    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
#  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)
{
    (void)opaque;
    return _halloc((long)items, size);
}

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));
#endif

voidpf ZLIB_INTERNAL zcalloc (opaque, items, 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)
    voidpf opaque;
    voidpf ptr;
{
    (void)opaque;
    free(ptr);
}

#endif /* MY_ZCALLOC */

#endif /* !Z_SOLO */







|
<




|
<












|
|
|


|
<
<
<
<





|
<
<
<







256
257
258
259
260
261
262
263

264
265
266
267
268

269
270
271
272
273
274
275
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) {

    (void)opaque;
    return _halloc((long)items, size);
}

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(uInt size);
extern voidp calloc(uInt items, uInt size);
extern void free(voidpf ptr);
#endif

voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {




    (void)opaque;
    return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
                              (voidpf)calloc(items, size);
}

void ZLIB_INTERNAL zcfree(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
/* zutil.h -- internal interface and configuration of the compression library
 * Copyright (C) 1995-2016 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.
 */

|







1
2
3
4
5
6
7
8
9
/* zutil.h -- internal interface and configuration of the compression library
 * 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
#  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;












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_RETURN(strm,err) \
  return (strm->msg = ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */

        /* common constants */








<
<
<
<












>
>
>
>
>
>
>
>
>
>
>




|







25
26
27
28
29
30
31




32
33
34
35
36
37
38
39
40
41
42
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





#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[(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
#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)
#  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__)







|

<
<
<
<
<
<
<
<
<







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)
#  define OS_CODE  7









#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
#  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));
#endif

        /* common defaults */

#ifndef OS_CODE
#  define OS_CODE  3     /* assume Unix */
#endif







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









|
>
|







157
158
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(__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(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
#    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));
#endif

/* Diagnostic functions */
#ifdef ZLIB_DEBUG
#  include <stdio.h>
   extern int ZLIB_INTERNAL z_verbose;
   extern void ZLIB_INTERNAL z_error OF((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));
#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 */







|
|
|






|
















|
|
|












207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
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(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(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(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
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_Access\fR(\fIpath\fR, \fImode\fR)
.sp
int
\fBTcl_Stat\fR(\fIpath\fR, \fIstatPtr\fR)

.SH ARGUMENTS
.AS "struct stat" *statPtr out
.AP 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







>


|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
\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 "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

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
.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)
.sp

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

.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
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
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.
.AP Tcl_Obj *errorObjPtr in
The \fB\-errorcode\fR return option will be set to this value.
.AP char *element in
String to record as one element of the \fB\-errorcode\fR return option.
Last \fIelement\fR argument must be 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)

.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

.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







|














|

>







<

>








|










|


|


|


<
<
<



|
>

|
>
|
|
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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

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, ... \fBNULL\fR)
.sp
int
\fBTcl_GetErrorLine\fR(\fIinterp\fR)
.sp
\fBTcl_SetErrorLine\fR(\fIinterp, lineNum\fR)
.sp
const char *
\fBTcl_PosixError\fR(\fIinterp\fR)
.sp

\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 "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 Tcl_Size length in
The number of bytes to copy from \fImessage\fR when
appending to the \fB\-errorinfo\fR return option.
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 "const char" *element in
String to record as one element of the \fB\-errorcode\fR return option.
Last \fIelement\fR argument must be NULL.



.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 <= \fIcommand\fR).
.AP "const char" *command in
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
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 "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







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





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
'\"
'\" 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"
.so man.macros
.BS
.SH NAME
Tcl_Alloc, Tcl_Free, Tcl_Realloc, Tcl_AttemptAlloc, Tcl_AttemptRealloc \- allocate or free heap memory
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
char *
\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)



.SH ARGUMENTS
.AS char *size
.AP "unsigned int" size in
Size in bytes of the memory block to allocate.
.AP char *ptr in
Pointer to memory block to free or realloc.


.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






|



|







<










>
>
>


|



>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
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 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
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 *
\fBTcl_Alloc\fR(\fIsize\fR)
.sp

\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 "size_t" size in
Size in bytes of the memory block to allocate.
.AP char *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
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.








.SH KEYWORDS
alloc, allocation, free, malloc, memory, realloc, TCL_MEM_DEBUG







>
>
>
>
>
>
>



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

.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter in which script will be evaluated.
.BE

.SH DESCRIPTION







>







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
Tcl_AppInit \- perform application-specific initialization
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_AppInit\fR(\fIinterp\fR)

.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter for the application.
.BE

.SH DESCRIPTION







>







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

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







>







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
'\"
'\" 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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_AsyncHandler
\fBTcl_AsyncCreate\fR(\fIproc, clientData\fR)
.sp

\fBTcl_AsyncMark\fR(\fIasync\fR)
.sp



int
\fBTcl_AsyncInvoke\fR(\fIinterp, code\fR)
.sp

\fBTcl_AsyncDelete\fR(\fIasync\fR)
.sp
int
\fBTcl_AsyncReady\fR()

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











|







>


>
>
>



>




>








>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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_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
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.
.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.
\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,







|
|
|
>
|








|
|
>
>
|
>
|
|
|
|







64
65
66
67
68
69
70
71
72
73
74
75
76
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_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 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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_BackgroundException\fR(\fIinterp, code\fR)
.sp
\fBTcl_BackgroundError\fR(\fIinterp\fR)

.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







>







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
'\"
'\" 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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewBooleanObj\fR(\fIboolValue\fR)
.sp
\fBTcl_SetBooleanObj\fR(\fIobjPtr, boolValue\fR)
.sp
int
\fBTcl_GetBooleanFromObj\fR(\fIinterp, objPtr, boolPtr\fR)




.SH ARGUMENTS
.AS Tcl_Interp boolValue in/out
.AP int boolValue 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
Points to place where \fBTcl_GetBooleanFromObj\fR
stores the boolean value (0 or 1) obtained from \fIobjPtr\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
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.
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
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
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
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 "SEE ALSO"
Tcl_NewObj, Tcl_IsShared, Tcl_GetBoolean

.SH KEYWORDS
boolean, value











|





|

|



>
>
>
>

|
|








|


>
>
>
>
>
>
>






|




|




|


|




















>
>
>
>
>













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





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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, Tcl_GetBoolFromObj \- store/retrieve boolean value in a Tcl_Obj
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewBooleanObj\fR(\fIintValue\fR)
.sp
\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 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 "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 \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 \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 \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 \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
'\"
'\" 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"
.so man.macros
.BS
.SH NAME
Tcl_NewByteArrayObj, Tcl_SetByteArrayObj, Tcl_GetByteArrayFromObj, Tcl_SetByteArrayLength \- manipulate Tcl values as a arrays of bytes
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewByteArrayObj\fR(\fIbytes, length\fR)
.sp
void
\fBTcl_SetByteArrayObj\fR(\fIobjPtr, bytes, length\fR)
.sp

unsigned char *




\fBTcl_GetByteArrayFromObj\fR(\fIobjPtr, lengthPtr\fR)
.sp
unsigned char *
\fBTcl_SetByteArrayLength\fR(\fIobjPtr, length\fR)

.SH ARGUMENTS
.AS "const unsigned char" *lengthPtr 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.
.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
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.





.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
string representation of a byte-array value (by calling
\fBTcl_GetStringFromObj\fR) produces a properly formed UTF-8 sequence with a
one-to-one mapping between the bytes in the internal representation and the
UTF-8 characters in the string representation.
.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.








.PP



\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
\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
modified by the caller only if the value is not shared and the caller
invalidates the string representation.
.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
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,
the length of array is reduced to the new length.  The return value is a
pointer to the value's new array of bytes.



















.SH "SEE ALSO"
Tcl_GetStringFromObj, Tcl_NewObj, Tcl_IncrRefCount, Tcl_DecrRefCount

.SH KEYWORDS
value, binary data, byte array, utf, unicode, internationalization






|



|





|

<
|

>

>
>
>
>
|


|
>

|


|
|
|

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

<


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

|
<
|

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

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

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





|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

152
153
154

155
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 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
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, numBytes\fR)
.sp

\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, numBytesPtr\fR)
.sp
unsigned char *
\fBTcl_SetByteArrayLength\fR(\fIobjPtr, numBytes\fR)
.fi
.SH ARGUMENTS
.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 \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 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.

.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 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 this string in Tcl's usual

Modified UTF-8 encoding.
.PP
\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
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

contents of the internal representation, so long as the value is unshared

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 8.7.
.PP
\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

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

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

Changes to doc/CallDel.3.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
.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)

.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







>







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

.SH "SEE ALSO"
Tcl_CreateExitHandler(3), Tcl_CreateThreadExitHandler(3)
.SH KEYWORDS
callback, cleanup, delete, interpreter







|
>




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.
.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
.nf
\fB#include <tcl.h>\fR
int
\fBTcl_CancelEval\fR(\fIinterp, resultObjPtr, clientData, flags\fR)
.sp
int
\fBTcl_Canceled\fR(\fIinterp, flags\fR)

.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.
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
\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 "SEE ALSO"
interp(n), Tcl_Eval(3),
TIP 285
.SH KEYWORDS
cancel, unwind







>









|




















|



















>
>
>
>
>
>
>
>





13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
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 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
'\"
'\" 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
.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













<













|







1
2
3
4
5
6
7
8
9
10
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

\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)
.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

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
.sp
\fBTcl_ClassSetMetadata\fR(\fIclass, metaTypePtr, metadata\fR)
.sp
Tcl_ObjectMapMethodNameProc
\fBTcl_ObjectGetMethodNameMapper\fR(\fIobject\fR)
.sp
\fBTcl_ObjectSetMethodNameMapper\fR(\fIobject\fR, \fImethodNameMapper\fR)









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







>
>
>
>
>
>
>
>
>


















|



|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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 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 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
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.







.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







>
>
>
>
>
>
>







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







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








253
254
255
256
257
258
259
260
261
262
263
264
265
266
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
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)

.SH ARGUMENTS
.AS "const char" *cmd
.AP "const char" *cmd in
Command string to test for completeness.
.BE

.SH DESCRIPTION







>







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
Tcl_Concat \- concatenate a collection of strings
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
const char *
\fBTcl_Concat\fR(\fIargc, argv\fR)

.SH ARGUMENTS
.AS "const char *const" argv[]
.AP int 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







>


|







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 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
'\"
'\" 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
.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 *










|







<
<
<







1
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) 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_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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_IsSafe\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 *
48
49
50
51
52
53
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
                objcPtr, objvPtr\fR)
.sp
int
\fBTcl_ExposeCommand\fR(\fIinterp, hiddenCmdName, cmdName\fR)
.sp
int
\fBTcl_HideCommand\fR(\fIinterp, cmdName, hiddenCmdName\fR)

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







>




















|




|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
                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 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 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
134
135
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 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.







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







132
133
134
135
136
137
138












139
140
141
142
143
144
145
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_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
\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_GetAlias\fR returns information 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
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







>
|






|
|
|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
\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
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
pointer to the string containing the name of the target command.
.PP
\fBTcl_GetAlias\fR is similar to \fBTcl_GetAliasObj\fR except that it
returns a pointer to a vector of string instead of a vector of
Tcl_Obj structures. \fBTcl_GetAlias\fR is deprecated.
.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
224
225
226
227
228
229
230








231
232
233
234
235
236
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 "SEE ALSO"
interp

.SH KEYWORDS
alias, command, exposed commands, hidden commands, interpreter, invoke,
parent, child







>
>
>
>
>
>
>
>

|




211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
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(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
.sp
Tcl_ThreadId
\fBTcl_GetChannelThread\fR(\fIchannel\fR)
.sp
int
\fBTcl_GetChannelMode\fR(\fIchannel\fR)
.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)







>
>
>
>
>



















<


<


<







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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

\fBTcl_CutChannel\fR(\fIchannel\fR)
.sp

\fBTcl_SpliceChannel\fR(\fIchannel\fR)
.sp

\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
\fBTcl_ChannelGetHandleProc\fR(\fItypePtr\fR)
.sp
Tcl_DriverFlushProc *
\fBTcl_ChannelFlushProc\fR(\fItypePtr\fR)
.sp
Tcl_DriverHandlerProc *
\fBTcl_ChannelHandlerProc\fR(\fItypePtr\fR)
.sp
.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







|







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







|







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







>
>
>
>
>
>
>
>
>
>

















>
|







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
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).
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
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 {
        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;







|







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







<







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
.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(
        void *\fIinstanceData\fR,
        Tcl_WideInt \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







|

|







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 long long \fBTcl_DriverWideSeekProc\fR(
        void *\fIinstanceData\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
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);
.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.







|







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







<


<


<

|








|







8
9
10
11
12
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

\fB#include <tcl.h>\fR
.sp

\fBTcl_CreateChannelHandler\fR(\fIchannel, mask, proc, clientData\fR)
.sp

\fBTcl_DeleteChannelHandler\fR(\fIchannel, proc, clientData\fR)
.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_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

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
'\" 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
.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







<


<

|







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

\fBTcl_CreateCloseHandler\fR(\fIchannel, proc, clientData\fR)
.sp

\fBTcl_DeleteCloseHandler\fR(\fIchannel, proc, clientData\fR)
.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
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)

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







>









|







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

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







>



<
|







89
90
91
92
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
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.

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

Changes to doc/CrtFileHdlr.3.

13
14
15
16
17
18
19

20
21
22
23
24
25
26
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_CreateFileHandler\fR(\fIfd, mask, proc, clientData\fR)
.sp
\fBTcl_DeleteFileHandler\fR(\fIfd\fR)

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







>







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
\fBTcl_DeleteInterp\fR(\fIinterp\fR)
.sp
int
\fBTcl_InterpDeleted\fR(\fIinterp\fR)
.sp
int
\fBTcl_InterpActive\fR(\fIinterp\fR)

.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Token for interpreter to be destroyed or queried.
.BE
.SH DESCRIPTION
.PP







>







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
'\"
'\" 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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Command
\fBTcl_CreateObjCommand\fR(\fIinterp, cmdName, proc, clientData, deleteProc\fR)
.sp



int
\fBTcl_DeleteCommand\fR(\fIinterp, cmdName\fR)
.sp
int
\fBTcl_DeleteCommandFromToken\fR(\fIinterp, token\fR)
.sp
int










|







>
>
>







1
2
3
4
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_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
.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
.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
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 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







<




|
<
<
<
<
<
<
<




|




>
>
>







36
37
38
39
40
41
42

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

\fBTcl_GetCommandFullName\fR(\fIinterp, token, objPtr\fR)
.sp
Tcl_Command
\fBTcl_GetCommandFromObj\fR(\fIinterp, objPtr\fR)
.fi







.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 "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
176
177
178
179
180
181
182











183
184
185
186
187
188
189
.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_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.







>
>
>
>
>
>
>
>
>
>
>







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
.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
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 {
    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;


} \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.
It allows a program to determine whether it is faster to
call \fIobjProc\fR or \fIproc\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







|








>
>



|
>
|
|

|
|
>
>







219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
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 {
    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 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 \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
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
\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







<
|







290
291
292
293
294
295
296

297
298
299
300
301
302
303
304
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.

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
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
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
string which was registered, and not a copy; use of a compile-time constant
string is \fIstrongly recommended\fR.
.VE "info cmdtype feature"
.SH "SEE ALSO"
Tcl_CreateCommand(3), Tcl_ResetResult(3), Tcl_SetObjResult(3)
.SH KEYWORDS
bind, command, create, delete, namespace, value







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




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

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

\fIobjPtr\fR argument; it only reads.

.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
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_TimerToken
\fBTcl_CreateTimerHandler\fR(\fImilliseconds, proc, clientData\fR)
.sp
\fBTcl_DeleteTimerHandler\fR(\fItoken\fR)

.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







>







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
'\"
'\" 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 <[email protected]>.  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
.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



\fBTcl_DeleteTrace\fR(\fIinterp, trace\fR)

.SH ARGUMENTS
.AS Tcl_CmdObjTraceDeleteProc *deleteProc
.AP Tcl_Interp *interp in
Interpreter containing command to be traced or untraced.
.AP int 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_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.
.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).



|








|










>
>
>

>




|











>
>
>




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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 Kevin B. Kenny <[email protected]>.  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_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 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, \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
        \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
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







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







77
78
79
80
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
.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
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







|
<
<
<
<







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.




.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
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 KEYWORDS
command, create, delete, interpreter, trace







>
>
>
>
>
>
>
>
>


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
'\"
'\" 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
.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
\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)





.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,
add all characters up to null terminating character.
.AP size_t 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












|
















|












>
>
>
>
>








|
|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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, 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
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 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 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
.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.




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











.SH KEYWORDS
append, dynamic string, free, result







>
>
>
>






>
>
>
>
>
>
>
>
>
>



137
138
139
140
141
142
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
.sp
\fBTcl_DetachPids\fR(\fInumPids, pidPtr\fR)
.sp
\fBTcl_ReapDetachedProcs\fR()
.sp
Tcl_Pid
\fBTcl_WaitPid\fR(\fIpid, statusPtr, options\fR)

.SH ARGUMENTS
.AS Tcl_Pid *statusPtr out
.AP int 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.







>


|







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

.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







<


<







>







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

\fBTcl_DictObjNext\fR(\fIsearchPtr, keyPtrPtr, valuePtrPtr, donePtr\fR)
.sp

\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
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
Points to a variable that will have the number of key/value pairs
contained within the dictionary placed within it.





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







|


>
>
>
>
>











|







65
66
67
68
69
70
71
72
73
74
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 "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 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
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.

.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







|
>







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







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







191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
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
Tcl_DoOneEvent \- wait for events and invoke event handlers
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_DoOneEvent\fR(\fIflags\fR)

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







>







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
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 \-
Process window system events.
.TP 27
\fBTCL_FILE_EVENTS\fR \-
Process file events.
.TP 27
\fBTCL_TIMER_EVENTS\fR \-
Process timer events.
.TP 27
\fBTCL_IDLE_EVENTS\fR \-
Process idle callbacks.
.TP 27
\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 \-
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







<
|

<
|

<
|

<
|

<
|


<
|







50
51
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:

.IP \fBTCL_WINDOW_EVENTS\fR
Process window system events.

.IP \fBTCL_FILE_EVENTS\fR
Process file events.

.IP \fBTCL_TIMER_EVENTS\fR
Process timer events.

.IP \fBTCL_IDLE_EVENTS\fR
Process idle callbacks.

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

.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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_DoWhenIdle\fR(\fIproc, clientData\fR)
.sp
\fBTcl_CancelIdleCall\fR(\fIproc, clientData\fR)

.SH ARGUMENTS
.AS Tcl_IdleProc clientData
.AP Tcl_IdleProc *proc in
Procedure to invoke.
.AP coid *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







>




|







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 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
Tcl_Obj *
\fBTcl_NewDoubleObj\fR(\fIdoubleValue\fR)
.sp
\fBTcl_SetDoubleObj\fR(\fIobjPtr, doubleValue\fR)
.sp
int
\fBTcl_GetDoubleFromObj\fR(\fIinterp, objPtr, doublePtr\fR)

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







>







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

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 "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult
.SH KEYWORDS
double, double value, double type, internal representation, value, value type, string representation








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



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

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
'\"
'\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans.
'\" Copyright (c) 2000 by 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)

.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

|
|














<


<

|







1
2
3
4
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 & 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

\fBTcl_InitMemory\fR(\fIinterp\fR)
.sp

\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
'\"
'\" 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
.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



char *
\fBTcl_UtfToExternalDString\fR(\fIencoding, src, srcLen, dstPtr\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



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)

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










|







<








>
>
>



>
>
>











>
>
>






<










>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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_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

\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

\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
.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
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.
\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
return immediately upon reading a source character that does not exist in
the target encoding; otherwise a default fallback character will
automatically be substituted.



.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







|






|







|
>
>
>
|
<
<
|
>
>
>







81
82
83
84
85
86
87
88
89
90
91
92
93
94
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 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
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. 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,


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







>
>
>







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







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







206
207
208
209
210
211
212
213
214
215
216
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
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
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.
.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_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_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







|
|



|











>
>
>
>
>
>
>
>
>
>














>
>
>







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
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 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.
.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
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 {
    const char *\fIencodingName\fR;
    Tcl_EncodingConvertProc *\fItoUtfProc\fR;
    Tcl_EncodingConvertProc *\fIfromUtfProc\fR;
    Tcl_EncodingFreeProc *\fIfreeProc\fR;
    void *\fIclientData\fR;
    int \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.







|





|







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 {
    const char *\fIencodingName\fR;
    Tcl_EncodingConvertProc *\fItoUtfProc\fR;
    Tcl_EncodingConvertProc *\fIfromUtfProc\fR;
    Tcl_EncodingFreeProc *\fIfreeProc\fR;
    void *\fIclientData\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
.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
.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
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 KEYWORDS
utf, encoding, convert







|
|
|
|
|
|
|











|







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


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
.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
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
\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)

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







>













|






|







52
53
54
55
56
57
58
59
60
61
62
63
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 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 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
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







>







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
.
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 "SEE ALSO"
namespace(n), Tcl_DeleteCommandFromToken(3)
.SH KEYWORDS
command, ensemble







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




207
208
209
210
211
212
213
214
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
Tcl_PutEnv \- procedures to manipulate the environment
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_PutEnv\fR(\fIassignment\fR)

.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







>







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

.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.
\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;
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
String forming part of a Tcl script.
.BE

.SH DESCRIPTION
.PP
The procedures described here are invoked to execute Tcl scripts in
various forms.







|
>








|



|
|










|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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, ... \fBNULL\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
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 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 "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
.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
(^Z) for all platforms. If you require a
.QW ^Z
in code for string comparison, you can use
.QW \e032
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
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.







|



|
<
<



|







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 \ex1A
(^Z) for all platforms. If you require a
.QW ^Z
in code for string comparison, you can use
.QW \ex1A ,


which will be safely substituted by the Tcl interpreter into
.QW ^Z .
.PP
\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.
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
.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.

.SH "FLAG BITS"
.PP
Any ORed 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







|



|







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
.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.

.SH "FLAG BITS"
.PP
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
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 KEYWORDS
execute, file, global, result, script, value







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



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
.sp
\fBTcl_CreateThreadExitHandler\fR(\fIproc, clientData\fR)
.sp
\fBTcl_DeleteThreadExitHandler\fR(\fIproc, clientData\fR)
.sp
Tcl_ExitProc *
\fBTcl_SetExitProc\fR(\fIproc\fR)

.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
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
invoked anyplace else to terminate the application.
No-one should ever invoke the \fBexit\fR system procedure 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
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
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







>




|
|
















|

|

|


|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
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 Tcl command, and can be
invoked anyplace else to terminate the application.
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 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
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

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








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

Changes to doc/ExprLong.3.

21
22
23
24
25
26
27

28
29
30
31
32
33
34
\fBTcl_ExprDouble\fR(\fIinterp, expr, doublePtr\fR)
.sp
int
\fBTcl_ExprBoolean\fR(\fIinterp, expr, booleanPtr\fR)
.sp
int
\fBTcl_ExprString\fR(\fIinterp, expr\fR)

.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







>







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

.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







>







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
.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 "SEE ALSO"
Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean, Tcl_ExprString, Tcl_GetObjResult

.SH KEYWORDS
boolean, double, evaluate, expression, integer, value, string







>
>
>
>
>
>
>
>
>






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.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
.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)







<







19
20
21
22
23
24
25

26
27
28
29
30
31
32
.sp
int
\fBTcl_FSUnregister\fR(\fIfsPtr\fR)
.sp
void *
\fBTcl_FSData\fR(\fIfsPtr\fR)
.sp

\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
int
\fBTcl_FSCreateDirectory\fR(\fIpathPtr\fR)
.sp
int
\fBTcl_FSDeleteFile\fR(\fIpathPtr\fR)
.sp
int
\fBTcl_FSRemoveDirectory\fR(\fIpathPtr, int recursive, errorPtr\fR)
.sp
int
\fBTcl_FSRenameFile\fR(\fIsrcPathPtr, destPathPtr\fR)
.sp
Tcl_Obj *
\fBTcl_FSListVolumes\fR(\fIvoid\fR)
.sp







|







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, 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
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)
.sp
int
\fBTcl_FSFileAttrsSet\fR(\fIinterp, int index, pathPtr, Tcl_Obj *objPtr\fR)
.sp
const char *const *
\fBTcl_FSFileAttrStrings\fR(\fIpathPtr, objPtrRef\fR)
.sp
int
\fBTcl_FSStat\fR(\fIpathPtr, statPtr\fR)
.sp







|


|







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, index, pathPtr, objPtrRef\fR)
.sp
int
\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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184

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


200
201
202
203
204
205
206
.sp
Tcl_Obj *
\fBTcl_FSFileSystemInfo\fR(\fIpathPtr\fR)
.sp
Tcl_StatBuf *
\fBTcl_AllocStatBuf\fR()
.sp
Tcl_WideInt
\fBTcl_GetAccessTimeFromStat\fR(\fIstatPtr\fR)
.sp
unsigned
\fBTcl_GetBlockSizeFromStat\fR(\fIstatPtr\fR)
.sp
Tcl_WideUInt
\fBTcl_GetBlocksFromStat\fR(\fIstatPtr\fR)
.sp
Tcl_WideInt
\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
\fBTcl_GetModificationTimeFromStat\fR(\fIstatPtr\fR)
.sp
Tcl_WideUInt
\fBTcl_GetSizeFromStat\fR(\fIstatPtr\fR)
.sp
int
\fBTcl_GetUserIdFromStat\fR(\fIstatPtr\fR)

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







|





|


|




















|


|




>















>
>







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
.sp
Tcl_Obj *
\fBTcl_FSFileSystemInfo\fR(\fIpathPtr\fR)
.sp
Tcl_StatBuf *
\fBTcl_AllocStatBuf\fR()
.sp
long long
\fBTcl_GetAccessTimeFromStat\fR(\fIstatPtr\fR)
.sp
unsigned
\fBTcl_GetBlockSizeFromStat\fR(\fIstatPtr\fR)
.sp
unsigned long long
\fBTcl_GetBlocksFromStat\fR(\fIstatPtr\fR)
.sp
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
long long
\fBTcl_GetModificationTimeFromStat\fR(\fIstatPtr\fR)
.sp
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 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
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
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 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
\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
Filled with the init function for this code.
.AP Tcl_PackageInitProc **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_Obj *basePtr in
The base path on to which to join the given elements. May be NULL.
.AP int 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







|
|




>
>
>
>



|













|

|



















|
|
>
>
>
>
>


|







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
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 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
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_LibraryInitProc **proc1Ptr out
Filled with the init function for this code.
.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 "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 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
362
363
364
365
366
367
368
369

370
371
372
373
374
375
376
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

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







|
>







373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
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
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
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
(^Z) for all platforms.
If you require a
.QW ^Z
in code for string comparison, you can use
.QW \e032
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







|




|
<
<







427
428
429
430
431
432
433
434
435
436
437
438
439


440
441
442
443
444
445
446
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 \ex1A
(^Z) for all platforms.
If you require a
.QW ^Z
in code for string comparison, you can use
.QW \ex1A ,


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

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







|
|
>







484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
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 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
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
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







|







652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
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 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
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







<
<
<
<
<







681
682
683
684
685
686
687





688
689
690
691
692
693
694
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.





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







|
<
<
<
<
<
<
<







702
703
704
705
706
707
708
709







710
711
712
713
714
715
716
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. 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.
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
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 {
    const char *\fItypeName\fR;
    int \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;







|

|







839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
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 {
    const char *\fItypeName\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
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
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.







|
<
<







1059
1060
1061
1062
1063
1064
1065
1066


1067
1068
1069
1070
1071
1072
1073
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 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
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 {
    /* 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 */







|







1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
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 {
    /* 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
        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.
.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







|
|
|
|







1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
        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.
.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
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 "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







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




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
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
.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
\fBTcl_FindExecutable\fR(\fIargv0\fR)
.sp
const char *
\fBTcl_GetNameOfExecutable\fR()

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







|




>
















>
>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
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
.nf
\fB#include <tcl.h>\fR
.sp
char *
\fBTcl_GetCwd\fR(\fIinterp\fR, \fIbufferPtr\fR)
.sp
int
\fBTcl_Chdir\fR(\fIpath\fR)

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

.SH KEYWORDS
pwd







|
>









|

















|
|



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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(\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 "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 \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
'\"
'\" Copyright (c) 1998-2000 by 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()

.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

|













>







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 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
int
\fBTcl_GetIndexFromObj\fR(\fIinterp, objPtr, tablePtr, msg, flags,
indexPtr\fR)
.sp
int
\fBTcl_GetIndexFromObjStruct\fR(\fIinterp, objPtr, structTablePtr, offset,
                          msg, flags, indexPtr\fR)

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







>







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


.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

the index 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
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 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 "SEE ALSO"
prefix(n), Tcl_WrongNumArgs(3)
.SH KEYWORDS
index, option, value, table lookup







|
|
|
|
>
>












>
|
<















|



>
>
|













>
>
>
>
>
>




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

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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
, \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
of the matching entry is stored at \fI*indexPtr\fR.

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




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




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







|
>
>
>
>











|
|
>
>
>
>













|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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, 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 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.
.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
.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.
If \fIsrc\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\fR,
then 1 is stored at \fI*boolPtr\fR.
Any of these values may be abbreviated, and upper-case spellings
are also acceptable.





.SH KEYWORDS
boolean, conversion, double, floating-point, integer







|

|


>
>
>
>



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*intPtr\fR.
If \fIsrc\fR is any of \fB1\fR, \fBtrue\fR, \fByes\fR, or \fBon\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
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
.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







|







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)
.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
'\"
'\" 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.
'\"
.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
.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.

|


















|







1
2
3
4
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 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)
.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
'\"
'\" Copyright (c) 2001 by Kevin B. Kenny <[email protected]>.
'\"
'\" 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)

.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

|


















>







1
2
3
4
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 Kevin B. Kenny <[email protected]>.
'\"
'\" 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
.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;
    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
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







|
|







|







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 {
    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
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
.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)

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







>

<






|







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

.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 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
\fBTcl_FirstHashEntry\fR(\fItablePtr, searchPtr\fR)
.sp
Tcl_HashEntry *
\fBTcl_NextHashEntry\fR(\fIsearchPtr\fR)
.sp
char *
\fBTcl_HashStats\fR(\fItablePtr\fR)

.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







>







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
.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 {
    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;







|







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 {
    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
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 KEYWORDS
hash table, key, lookup, search, value







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


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
'\"
'\" Copyright (c) 1998-2000 by Scriptics Corporation.
'\" All rights reserved.
'\"
.TH Tcl_Init 3 8.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)




.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Interpreter to initialize.


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












.SH "SEE ALSO"
Tcl_AppInit, Tcl_Main

.SH KEYWORDS
application, initialization, interpreter

|


|










>
>
>
>




>
>









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


<


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 Scriptics Corporation.
'\" All rights reserved.
'\"
.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
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)

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







>







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







|
|







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

9
10
11
12
13
14
15
16
17


18
19
20
21
22
23



24
25
26
27
28
29
30
31
.BS
.SH NAME
Tcl_InitSubsystems \- initialize the Tcl library.
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
void
\fBTcl_InitSubsystems\fR(\fIvoid\fR)


.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



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







|
|
>
>






>
>
>



|




9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
.BS
.SH NAME
Tcl_InitSubsystems \- initialize the Tcl library.
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
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 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
'\"
'\" 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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Obj *
\fBTcl_NewIntObj\fR(\fIintValue\fR)
.sp










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
'\"
'\" 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_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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42






43
44
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
\fBTcl_SetWideIntObj\fR(\fIobjPtr, wideValue\fR)
.sp
int
\fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR)
.sp
int
\fBTcl_GetIntForIndex\fR(\fIinterp, objPtr, endValue, intPtr\fR)
.sp
int
\fBTcl_GetLongFromObj\fR(\fIinterp, objPtr, longPtr\fR)
.sp
int
\fBTcl_GetWideIntFromObj\fR(\fIinterp, objPtr, widePtr\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)

.SH ARGUMENTS
.AS Tcl_WideInt doubleValue in/out
.AP int 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.







|







>
>
>
>
>
>
















>


|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
.sp
\fBTcl_SetWideIntObj\fR(\fIobjPtr, wideValue\fR)
.sp
int
\fBTcl_GetIntFromObj\fR(\fIinterp, objPtr, intPtr\fR)
.sp
int
\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 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.
76
77
78
79
80
81
82


83
84




85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
.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_WideInt *widePtr out
Points to place to store the wide 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.
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.







>
>


>
>
>
>




















|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
.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, 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.
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
\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_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,







|
>







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
\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_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
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 "SEE ALSO"
Tcl_NewObj, Tcl_DecrRefCount, Tcl_IncrRefCount, Tcl_GetObjResult
.SH KEYWORDS
integer, integer value, integer type, internal representation, value,
value type, string representation







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





170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
.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)

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







<


<





<


<


<





<


<


<

>








|







24
25
26
27
28
29
30

31
32

33
34
35
36
37

38
39

40
41

42
43
44
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

\fBTcl_LimitTypeSet\fR(\fIinterp, type\fR)
.sp

\fBTcl_LimitTypeReset\fR(\fIinterp, type\fR)
.sp
int
\fBTcl_LimitGetCommands\fR(\fIinterp\fR)
.sp

\fBTcl_LimitSetCommands\fR(\fIinterp, commandLimit\fR)
.sp

\fBTcl_LimitGetTime\fR(\fIinterp, timeLimitPtr\fR)
.sp

\fBTcl_LimitSetTime\fR(\fIinterp, timeLimitPtr\fR)
.sp
int
\fBTcl_LimitGetGranularity\fR(\fIinterp, type\fR)
.sp

\fBTcl_LimitSetGranularity\fR(\fIinterp, type, granularity\fR)
.sp

\fBTcl_LimitAddHandler\fR(\fIinterp, type, handlerProc, clientData, deleteProc\fR)
.sp

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

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







>







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







|





|







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_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 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
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.
.VE "TIP 312"
.RE
.TP
\fBTCL_LINK_BYTES\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







|



|







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_BINARY\fR instead.
.VE "TIP 312"
.RE
.TP
\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
.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
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
.







|
<
<







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
wideinteger form acceptable to \fBTcl_GetWideUIntFromObj\fR;


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
.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)
.sp
int
\fBTcl_ListObjIndex\fR(\fIinterp, listPtr, index, objPtrPtr\fR)
.sp
int
\fBTcl_ListObjReplace\fR(\fIinterp, listPtr, first, count, objc, objv\fR)

.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







|






>







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, 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
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
Points to location where \fBTcl_ListObjGetElements\fR
stores the number of element values in \fIlistPtr\fR.





.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
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
Points to location where \fBTcl_ListObjLength\fR
stores the length of the list.





.AP int 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
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
The number of elements that \fBTcl_ListObjReplace\fR
is to replace.
.BE

.SH DESCRIPTION
.PP
Tcl list values have an internal representation that supports







|


>
>
>
>
>



|










|


>
>
>
>
>
|






|



|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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 "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 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 "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 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 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 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
.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.


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







|
>
>








<







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

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







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





254
255
256
257
258
259
260
261
262
263
264
265
266
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
\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)

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







>







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







>
>
>
>








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
.sp
Tcl_Method
\fBTcl_ObjectContextMethod\fR(\fIcontext\fR)
.sp
Tcl_Object
\fBTcl_ObjectContextObject\fR(\fIcontext\fR)
.sp
int
\fBTcl_ObjectContextSkippedArgs\fR(\fIcontext\fR)

.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







|

>







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







|



|







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 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 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
.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 "SEE ALSO"
Class(3), oo::class(n), oo::define(n), oo::object(n)
.SH KEYWORDS
constructor, method, object

.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:







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

|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
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), 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
.\"
.\" Copyright (c) 2008 by Kevin B. Kenny.
.\" Copyright (c) 2018 by 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.
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
Tcl_Command
\fBTcl_NRCreateCommand\fR(\fIinterp, cmdName, proc, nreProc, clientData,
                    deleteProc\fR)
.sp




int
\fBTcl_NRCallObjProc\fR(\fIinterp, nreProc, 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
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_ObjCmdProc *nreProc in
Called instead of \fIproc\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
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.

|
|








|








>
>
>
>



>
>
>












<






|






>
>
>
>
>


>
>






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

43
44
45
46
47
48
49
50
51
52
53
54
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 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_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

\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 "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 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
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_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







>
>
>







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
.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:
.PP
.CS
int
\fITheCmdOldObjProc\fR(
    void *clientData,
    Tcl_Interp *interp,
    int objc,







|







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







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





|
|
239
240
241
242
243
244
245
246
247
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 \(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
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)
.sp
int
\fBTcl_SetNamespaceUnknownHandler(\fIinterp, nsPtr, handlerPtr\fR)

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







|


|
>







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\fR(\fIinterp, nsPtr\fR)
.sp
int
\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
.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
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.







|







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 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
.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 "SEE ALSO"
Tcl_CreateCommand(3), Tcl_ListObjAppendList(3), Tcl_SetVar(3)
.SH KEYWORDS
namespace, command







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




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

.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
Where to add the new event in the queue:  \fBTCL_QUEUE_TAIL\fR,
\fBTCL_QUEUE_HEAD\fR, or \fBTCL_QUEUE_MARK\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
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







<


<


<


<


<


<





<





<





<


<














<


<

>




















|

|
>










|







10
11
12
13
14
15
16

17
18

19
20

21
22

23
24

25
26

27
28
29
30
31

32
33
34
35
36

37
38
39
40
41

42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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

\fBTcl_CreateEventSource\fR(\fIsetupProc, checkProc, clientData\fR)
.sp

\fBTcl_DeleteEventSource\fR(\fIsetupProc, checkProc, clientData\fR)
.sp

\fBTcl_SetMaxBlockTime\fR(\fItimePtr\fR)
.sp

\fBTcl_QueueEvent\fR(\fIevPtr, position\fR)
.sp

\fBTcl_ThreadQueueEvent\fR(\fIthreadId, evPtr, position\fR)
.sp

\fBTcl_ThreadAlert\fR(\fIthreadId\fR)
.sp
Tcl_ThreadId
\fBTcl_GetCurrentThread\fR()
.sp

\fBTcl_DeleteEvents\fR(\fIdeleteProc, clientData\fR)
.sp
void *
\fBTcl_InitNotifier\fR()
.sp

\fBTcl_FinalizeNotifier\fR(\fIclientData\fR)
.sp
int
\fBTcl_WaitForEvent\fR(\fItimePtr\fR)
.sp

\fBTcl_AlertNotifier\fR(\fIclientData\fR)
.sp

\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

\fBTcl_ServiceModeHook\fR(\fImode\fR)
.sp

\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 int position in
Where to add the new event in the queue:  \fBTCL_QUEUE_TAIL\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 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
\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;
    long \fIusec\fR;
} \fBTcl_Time\fR;
.CE
.PP
The \fIusec\fR field should be less than 1000000.
.PP
Information provided to \fBTcl_SetMaxBlockTime\fR







|
|







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




.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







|












|



|


|







>
>
>
>







313
314
315
316
317
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 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 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 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 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
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 {
    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;







|







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

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








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

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 8.7 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
'\"
'\" 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
.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


int
\fBTcl_IsShared\fR(\fIobjPtr\fR)
.sp
\fBTcl_InvalidateStringRep\fR(\fIobjPtr\fR)

.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










|














>
>



|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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_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)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
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;
    char *\fIbytes\fR;
    size_t \fIlength\fR;
    const Tcl_ObjType *\fItypePtr\fR;
    union {
        long \fIlongValue\fR;
        double \fIdoubleValue\fR;
        void *\fIotherValuePtr\fR;
        Tcl_WideInt \fIwideValue\fR;
        struct {







|
|

|







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_Size \fIrefCount\fR;
    char *\fIbytes\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
.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.
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
when a reference is no longer needed and,
if the value's reference count drops to zero, frees its storage.



A value shared by different code or data structures has
\fIrefCount\fR greater than 1.
Incrementing a value's reference count 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.


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.




.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







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

|
<
|
>













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







277
278
279
280
281
282
283
284
285

286
287
288
289
290
291
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.  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, \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

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.  Incrementing a value's reference count

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





.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







>
>
>
>
>





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
'\"
'\" 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"
.so man.macros
.BS
.SH NAME
Tcl_RegisterObjType, Tcl_GetObjType, Tcl_AppendAllObjTypes, Tcl_ConvertToType  \- 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)
















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








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






|



|














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















>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
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
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.





































.SH "THE TCL_OBJTYPE STRUCTURE"
.PP
Extension writers can define new value types by defining four
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 {
    const char *\fIname\fR;
    Tcl_FreeInternalRepProc *\fIfreeIntRepProc\fR;
    Tcl_DupInternalRepProc *\fIdupIntRepProc\fR;
    Tcl_UpdateStringProc *\fIupdateStringProc\fR;
    Tcl_SetFromAnyProc *\fIsetFromAnyProc\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







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


|
<
|
|
|
|
|
|


|





>
>
>
>
>
>
>
>
>
>
>







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
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 to eight

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

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.























































































































































.SH "SEE ALSO"
Tcl_NewObj(3), Tcl_DecrRefCount(3), Tcl_IncrRefCount(3)
.SH KEYWORDS
internal representation, value, value type, string representation, type conversion








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

|

|
>
315
316
317
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_BounceRefCount(3)
.SH KEYWORDS
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
.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
\fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR)
.sp
int
\fBTcl_Read\fR(\fIchannel, readBuf, bytesToRead\fR)
.sp
size_t
\fBTcl_GetsObj\fR(\fIchannel, lineObjPtr\fR)
.sp
size_t
\fBTcl_Gets\fR(\fIchannel, lineRead\fR)
.sp
size_t
\fBTcl_Ungets\fR(\fIchannel, input, inputLen, addAtEnd\fR)
.sp
size_t
\fBTcl_WriteObj\fR(\fIchannel, writeObjPtr\fR)
.sp
size_t
\fBTcl_WriteChars\fR(\fIchannel, charBuf, bytesToWrite\fR)
.sp
size_t
\fBTcl_Write\fR(\fIchannel, byteBuf, bytesToWrite\fR)
.sp
size_t
\fBTcl_ReadRaw\fR(\fIchannel, readBuf, bytesToRead\fR)
.sp
size_t
\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
\fBTcl_Seek\fR(\fIchannel, offset, seekMode\fR)
.sp
Tcl_WideInt
\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
.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
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







<














|


|


|


|


|


|


|


|


|


|

















|


|










|












|







28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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

\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
Tcl_Size
\fBTcl_ReadChars\fR(\fIchannel, readObjPtr, charsToRead, appendFlag\fR)
.sp
Tcl_Size
\fBTcl_Read\fR(\fIchannel, readBuf, bytesToRead\fR)
.sp
Tcl_Size
\fBTcl_GetsObj\fR(\fIchannel, lineObjPtr\fR)
.sp
Tcl_Size
\fBTcl_Gets\fR(\fIchannel, lineRead\fR)
.sp
Tcl_Size
\fBTcl_Ungets\fR(\fIchannel, input, inputLen, addAtEnd\fR)
.sp
Tcl_Size
\fBTcl_WriteObj\fR(\fIchannel, writeObjPtr\fR)
.sp
Tcl_Size
\fBTcl_WriteChars\fR(\fIchannel, charBuf, bytesToWrite\fR)
.sp
Tcl_Size
\fBTcl_Write\fR(\fIchannel, byteBuf, bytesToWrite\fR)
.sp
Tcl_Size
\fBTcl_ReadRaw\fR(\fIchannel, readBuf, bytesToRead\fR)
.sp
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
long long
\fBTcl_Seek\fR(\fIchannel, offset, seekMode\fR)
.sp
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)
.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 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
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
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
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
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
The number of bytes to consume from \fIcharBuf\fR or \fIbyteBuf\fR and
output to the channel.
.AP Tcl_WideInt 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
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.







|








|












|










|


|







|







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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 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 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 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 Tcl_Size bytesToWrite in
The number of bytes to consume from \fIcharBuf\fR or \fIbyteBuf\fR and
output to the channel.
.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 "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
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
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.


.PP
Setting \fIcharsToRead\fR to \fB\-1\fR 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 there is not enough input currently
available:  \fBTcl_ReadChars\fR returns a short count rather than waiting
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







|














|
|
>
>

|






>
|
|
<







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 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. 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 -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
strict) or if there is not enough input currently available:
\fBTcl_ReadChars\fR returns a short count rather than waiting 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
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
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
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
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.
.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.
.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







|

|


|
|
|

















|
















|
|
|
|







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







|







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







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





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.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
.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.







|
|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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, 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
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 "unsigned int" flags in
ORed combination of \fBTCL_TCPSERVER\fR flags that specify additional
informations 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.







>
>

|
|







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



.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







|
>
>
>









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. 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
'\"  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
\fBTcl_SetPanicProc\fR(\fIpanicProc\fR)
.sp
void
\fBTcl_ConsolePanic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR)
.sp
.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







<


|


<

|






<
<
<
<







8
9
10
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

\fBTcl_Panic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR)
.sp
const char *
\fBTcl_SetPanicProc\fR(\fIpanicProc\fR)
.sp

\fBTcl_ConsolePanic\fR(\fIformat\fR, \fIarg\fR, \fIarg\fR, \fI...\fR)
.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 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
.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 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
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







>
>
>





|
<











68
69
70
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 in stub-enabled extensions.

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

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





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







>






|



>
>
>
>
>







11
12
13
14
15
16
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 "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
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
.
Enables the argument processor to provide help when passed the argument
.QW \fB\-help\fR .
.TP
\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
.
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







<
|
<


<
|
<



<
|
<







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:

.IP \fBTCL_ARGV_AUTO_HELP\fR

Enables the argument processor to provide help when passed the argument
.QW \fB\-help\fR .

.IP \fBTCL_ARGV_AUTO_REST\fR

Instructs the argument processor that arguments after
.QW \fB\-\-\fR
are to be unprocessed.

.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
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
.
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
.
This value marks the end of all option descriptors in the table. All other
fields are ignored.
.TP
\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
.
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
.
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)(
        void *\fIclientData\fR,
        Tcl_Interp *\fIinterp\fR,
        int \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.
.RE
.TP
\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
.
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
.
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
.
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 "SEE ALSO"
Tcl_GetIndexFromObj(3), Tcl_Main(3), Tcl_CreateObjCommand(3)
.SH KEYWORDS
argument, parse
'\" Local Variables:
'\" fill-column: 78
'\" End:







<
|
<



<
|
<


<
|
<




<
|
<


















<
|
<







|


|




|
|
|
|
|

<
|
<




<
|
<



<
|
<



<
|
<





>
>
>
>
>
>







95
96
97
98
99
100
101

102

103
104
105

106

107
108

109

110
111
112
113

114

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154

155

156
157
158
159

160

161
162
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:

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

.IP \fBTCL_ARGV_END\fR

This value marks the end of all option descriptors in the table. All other
fields are ignored.

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

.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

.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 Tcl_Size (\fBTcl_ArgvGenFuncProc\fR)(
        void *\fIclientData\fR,
        Tcl_Interp *\fIinterp\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, \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

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

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

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

.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
const char *
\fBTcl_ParseVar\fR(\fIinterp, start, termPtr\fR)
.sp
\fBTcl_FreeParse\fR(\fIusedParsePtr\fR)
.sp
int
\fBTcl_EvalTokensStandard\fR(\fIinterp, tokenPtr, numTokens\fR)

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







>










|







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







|







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 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
.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 {
    const char *\fIcommentStart\fR;
    int \fIcommentSize\fR;
    const char *\fIcommandStart\fR;
    int \fIcommandSize\fR;
    int \fInumWords\fR;
    Tcl_Token *\fItokenPtr\fR;
    int \fInumTokens\fR;
    ...
} \fBTcl_Parse\fR;

typedef struct Tcl_Token {
    int \fItype\fR;
    const char *\fIstart\fR;
    size_t \fIsize\fR;
    size_t \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.
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







|

|

|
|

|



|


|
|









|
<







191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
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 {
    const char *\fIcommentStart\fR;
    Tcl_Size \fIcommentSize\fR;
    const char *\fIcommandStart\fR;
    Tcl_Size \fIcommandSize\fR;
    Tcl_Size \fInumWords\fR;
    Tcl_Token *\fItokenPtr\fR;
    Tcl_Size \fInumTokens\fR;
    ...
} \fBTcl_Parse\fR;

typedef struct {
    int \fItype\fR;
    const char *\fIstart\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. 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
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
.
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
.
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
.
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
.
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
.
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
.
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
.
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
.
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







<
|
<












<
|
<



<
|
<






<
|
<


<
|
<


<
|
<





<
|
<













<
|
<







246
247
248
249
250
251
252

253

254
255
256
257
258
259
260
261
262
263
264
265

266

267
268
269

270

271
272
273
274
275
276

277

278
279

280

281
282

283

284
285
286
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:

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

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

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

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

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

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

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

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







<
|
<







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.

.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

.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








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

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

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







>







|
<













|







29
30
31
32
33
34
35
36
37
38
39
40
41
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 specification string as described for \fBpackage require\fR.

.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 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
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 KEYWORDS
package, present, provide, require, version
.SH "SEE ALSO"
package(n), Tcl_StaticPackage(3)







>
>
>
>



|
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_StaticLibrary(3)

Changes to doc/Preserve.3.

15
16
17
18
19
20
21

22
23
24
25
26
27
28
\fB#include <tcl.h>\fR
.sp
\fBTcl_Preserve\fR(\fIclientData\fR)
.sp
\fBTcl_Release\fR(\fIclientData\fR)
.sp
\fBTcl_EventuallyFree\fR(\fIclientData, freeProc\fR)

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







>







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.

Changes to doc/PrintDbl.3.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
.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)

.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







>







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

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







>







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
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 "SEE ALSO"
Tcl_EvalObjEx, Tcl_GetObjResult

.SH KEYWORDS
command, event, execute, history, interpreter, value, record







>
>
>
>
>
>





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

.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







>







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
'\" 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
.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
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
Tcl-level interface for querying this information.
.PP
To embed configuration information into their binary 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,







<

|











|











|


|







10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
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

\fBTcl_RegisterConfig\fR(\fIinterp, pkgName, configuration, valEncoding\fR)
.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 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 library and the generation of a
Tcl-level interface for querying this information.
.PP
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
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

.TP
::\fIpkgName\fR::\fBpkgconfig\fR list

Returns a list containing the names of all defined keys.

.TP
::\fIpkgName\fR::\fBpkgconfig\fR get \fIkey\fR

Returns the configuration value associated with the specified
\fIkey\fR.
.RE
.SH TCL_CONFIG
.PP
The \fBTcl_Config\fR structure contains the following fields:
.PP
.CS
typedef struct Tcl_Config {
    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







>


>

>


>
|
<






|







|
82
83
84
85
86
87
88
89
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 \fIkey\fR.

.RE
.SH TCL_CONFIG
.PP
The \fBTcl_Config\fR structure contains the following fields:
.PP
.CS
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, 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
.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
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
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
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
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
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
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







<








<














|






|





|















|



|


|







23
24
25
26
27
28
29

30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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

\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

\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 "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 "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 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 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 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 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
\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
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.







|







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







>







>







>








>






>



>



>

















>
















>




















>






>







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
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

\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;
    Tcl_RegExpIndices *\fImatches\fR;
    size_t \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;
} \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 "SEE ALSO"
re_syntax(n)
.SH KEYWORDS
match, pattern, regular expression, string, subexpression, Tcl_RegExpIndices, Tcl_RegExpInfo








>









>















|
|

|














|
|
|




















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



|
>
317
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_Size \fInsubs\fR;
    Tcl_RegExpIndices *\fImatches\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_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

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
'\"
'\" Copyright (c) 1997 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_SaveInterpState 3 8.1 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
Tcl_SaveInterpState, Tcl_RestoreInterpState, Tcl_DiscardInterpState \- 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)
.fi
.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.
.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.
.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
'\" 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
.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.
.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
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
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







<


<


<


<

|









|






|





|







10
11
12
13
14
15
16

17
18

19
20

21
22

23
24
25
26
27
28
29
30
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

\fBTcl_SetChannelError\fR(\fIchan, msg\fR)
.sp

\fBTcl_SetChannelErrorInterp\fR(\fIinterp, msg\fR)
.sp

\fBTcl_GetChannelError\fR(\fIchan, msgPtr\fR)
.sp

\fBTcl_GetChannelErrorInterp\fR(\fIinterp, msgPtr\fR)
.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. 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 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 \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
.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 "SEE ALSO"
Tcl_Close(3), Tcl_OpenFileChannel(3), Tcl_SetErrno(3)
.SH KEYWORDS
channel driver, error messages, channel type







>
>
>
>
>
>
>
>
>




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
'\"
'\" 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
.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



.SH ARGUMENTS
.AS int errorCode
.AP int errorCode in
A POSIX error code such as \fBENOENT\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.










|
















>
>
>




>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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, 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
\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.




.SH KEYWORDS
errno, error code, global variables







>
>
>



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
.BS
.SH NAME
Tcl_SetRecursionLimit \- set maximum allowable nesting depth in interpreter
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
int
\fBTcl_SetRecursionLimit\fR(\fIinterp, depth\fR)

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







|

>





|







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

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

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

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

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149


150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

217
218
219
220
221
\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)
.sp
\fBTcl_ResetResult\fR(\fIinterp\fR)
.sp
\fBTcl_TransferResult\fR(\fIsourceInterp, code, targetInterp\fR)
.sp
\fBTcl_AppendElement\fR(\fIinterp, element\fR)

.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
.SH DESCRIPTION
.PP
The procedures described here are utilities for manipulating the
result value in a Tcl interpreter.
The interpreter result may be either a Tcl value or a string.
For example, \fBTcl_SetObjResult\fR and \fBTcl_SetResult\fR
set the interpreter result to, respectively, a value and a string.
Similarly, \fBTcl_GetObjResult\fR and \fBTcl_GetStringResult\fR
return the interpreter result as a value and as a string.
The procedures always keep the string and value forms
of the interpreter result consistent.
For example, if \fBTcl_SetObjResult\fR is called to set
the result to a value,
then \fBTcl_GetStringResult\fR is called,
it will return the value's string representation.

.PP
\fBTcl_SetObjResult\fR
arranges for \fIobjPtr\fR to be the result for \fIinterp\fR,
replacing any existing result.
The result is left pointing to the value
referenced by \fIobjPtr\fR.
\fIobjPtr\fR's reference count is incremented
since there is now a new reference to it from \fIinterp\fR.
The reference count for any old result value
is decremented and the old result value is freed if no
references to it remain.
.PP
\fBTcl_GetObjResult\fR returns the result for \fIinterp\fR as a value.
The value's reference count is not incremented;
if the caller needs to retain a long-term pointer to the value
they should use \fBTcl_IncrRefCount\fR to increment its reference count
in order to keep it from being freed too early or accidentally changed.
.PP
\fBTcl_SetResult\fR
arranges for \fIresult\fR to be the result for the current Tcl
command in \fIinterp\fR, replacing any existing result.
The \fIfreeProc\fR argument specifies how to manage the storage
for the \fIresult\fR argument;
it is discussed in the section
\fBTHE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT\fR below.
If \fIresult\fR is \fBNULL\fR, then \fIfreeProc\fR is ignored
and \fBTcl_SetResult\fR
re-initializes \fIinterp\fR's result to point to an empty string.
.PP
\fBTcl_GetStringResult\fR returns the result for \fIinterp\fR as a string.
If the result was set to a value by a \fBTcl_SetObjResult\fR call,

the value form will be converted to a string and returned.
If the value's string representation contains null bytes,
this conversion will lose information.
For this reason, programmers are encouraged to
write their code to use the new value API procedures
and to call \fBTcl_GetObjResult\fR instead.
.PP
\fBTcl_ResetResult\fR clears the result for \fIinterp\fR
and leaves the result in its normal empty initialized state.
If the result is a value,
its reference count is decremented and the result is left
pointing to an unshared value representing an empty string.
If the result is a dynamically allocated string, its memory is free*d
and the result is left as a empty string.
\fBTcl_ResetResult\fR also clears the error state managed by
\fBTcl_AddErrorInfo\fR, \fBTcl_AddObjErrorInfo\fR,
and \fBTcl_SetErrorCode\fR.
.PP
\fBTcl_AppendResult\fR makes it easy to build up Tcl results in pieces.
It takes each of its \fIresult\fR arguments and appends them in order
to the current result associated with \fIinterp\fR.
If the result is in its initialized empty state (e.g. a command procedure
was just invoked or \fBTcl_ResetResult\fR was just called),
then \fBTcl_AppendResult\fR sets the result to the concatenation of
its \fIresult\fR arguments.
\fBTcl_AppendResult\fR may be called repeatedly as additional pieces
of the result are produced.
\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.
.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
controlled by the return code value \fIcode\fR in the same manner
as \fBTcl_GetReturnOptions\fR.


.SH "DEPRECATED INTERFACES"
.SS "OLD STRING PROCEDURES"
.PP
Use of the following procedures is deprecated
since they manipulate the Tcl result as a string.
Procedures such as \fBTcl_SetObjResult\fR
that manipulate the result as a value
can be significantly more efficient.
.PP
\fBTcl_AppendElement\fR is similar to \fBTcl_AppendResult\fR in
that it allows results to be built up in pieces.
However, \fBTcl_AppendElement\fR takes only a single \fIelement\fR
argument and it appends that argument to the current result
as a proper Tcl list element.
\fBTcl_AppendElement\fR adds backslashes or braces if necessary
to ensure that \fIinterp\fR's result can be parsed as a list and that
\fIelement\fR will be extracted as a single element.
Under normal conditions, \fBTcl_AppendElement\fR will add a space
character to \fIinterp\fR's result just before adding the new
list element, so that the list elements in the result are properly
separated.
However if the new list element is the first in a list or sub-list
(i.e. \fIinterp\fR's current result is empty, or consists of the
single character
.QW { ,
or ends in the characters
.QW " {" )
then no space is added.
.SH "THE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT"
.PP
\fBTcl_SetResult\fR's \fIfreeProc\fR argument specifies how
the Tcl system is to manage the storage for the \fIresult\fR argument.
If \fBTcl_SetResult\fR or \fBTcl_SetObjResult\fR are called
at a time when \fIinterp\fR holds a string result,
they do whatever is necessary to dispose of the old string result
(see the \fBTcl_Interp\fR manual entry for details on this).
.PP
If \fIfreeProc\fR is \fBTCL_STATIC\fR it means that \fIresult\fR
refers to an area of static storage that is guaranteed not to be
modified until at least the next call to \fBTcl_Eval\fR.
If \fIfreeProc\fR
is \fBTCL_DYNAMIC\fR it means that \fIresult\fR was allocated with a call
to \fBTcl_Alloc\fR and is now the property of the Tcl system.
\fBTcl_SetResult\fR will arrange for the string's storage to be
released by calling \fBTcl_Free\fR when it is no longer needed.
If \fIfreeProc\fR is \fBTCL_VOLATILE\fR it means that \fIresult\fR
points to an area of memory that is likely to be overwritten when
\fBTcl_SetResult\fR returns (e.g. it points to something in a stack frame).
In this case \fBTcl_SetResult\fR will make a copy of the string in
dynamically allocated storage and arrange for the copy to be the
result for the current Tcl command.
.PP
If \fIfreeProc\fR is not one of the values \fBTCL_STATIC\fR,
\fBTCL_DYNAMIC\fR, and \fBTCL_VOLATILE\fR, then it is the address
of a procedure that Tcl should call to free the string.
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);
.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 "SEE ALSO"
Tcl_AddErrorInfo, Tcl_CreateObjCommand, Tcl_SetErrorCode, Tcl_Interp,
Tcl_GetReturnOptions
.SH KEYWORDS
append, command, element, list, value, result, return value, interpreter







|






>



|

|

<
|

|


|
|
<
<
<
<

|

|





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

|
<

<
<
<
<
<
<
<

|
|
<
<
<

|
<
|
<
<
<
|
|
<
|

|
<
>
|
<
<
|
<
|

|
<
<
<
<
<
<
|
<
|

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

|
|
<
<
<
|
|

>
>



<
|
|
<
|

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






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






|
|
>





20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48




49
50
51
52
53
54
55
56
57
58
59

60

61

62

63

64

65
66
67

68







69
70
71



72
73

74



75
76

77
78
79

80
81


82

83
84
85






86

87
88
89

90





91


92
93
94

95
96
97
98
99



100
101
102
103
104
105
106
107

108
109

110
111
112



113
114


115
116
117

118
119
120
121
122
123
124
125
126










127


















128
129
130
131
132
133
134
135
136
137
138
139
140
141
\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, ... , \fBNULL\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
The interpreter get or set the result for.
.AP Tcl_Obj *objPtr in
A value to set the result to.
.AP char *result in

The string value set the result to, or to append to the existing result.
.AP "const char" *element in
The string value to append as a list element
to the existing result of \fIinterp\fR.
.AP Tcl_FreeProc *freeProc in
Pointer to a procedure to call to release storage at
\fIresult\fR.




.AP Tcl_Interp *sourceInterp in
The interpreter to transfer the result and return options from.
.AP Tcl_Interp *targetInterp in
The interpreter to transfer the result and return options to.
.AP int code in
Return code value that controls transfer of return options.
.BE
.SH DESCRIPTION
.PP
These procedures manipulate the result of an interpreter.  Some procedures
provide a Tcl_Obj interface while others provide a string interface.  For

example, \fBTcl_SetObjResult\fR accepts a Tcl_Obj and \fBTcl_SetResult\fR

accepts a char *.  Similarly, \fBTcl_GetObjResult\fR produces a Tcl_Obj * and

\fBTcl_GetStringResult\fR produces a char *.  The procedures can be mixed and

matched.  For example, if \fBTcl_SetObjResult\fR is called to set the result to

a Tcl_Obj value, and then \fBTcl_GetStringResult\fR is called, it returns a

char * (but see caveats below).
.PP
\fBTcl_SetObjResult\fR sets \fIobjPtr\fR as the result for \fIinterp\fR,

replacing any existing result.







.PP
\fBTcl_GetObjResult\fR returns the result for \fIinterp\fR, without
incrementing its reference count.



.PP
\fBTcl_SetResult\fR sets \fIresult\fR as the result for \fIinterp\fR, replacing

any existing result, and calls \fIfreeProc\fR to free \fIresult\fR.  See \fBTHE



TCL_FREEPROC ARGUMENT TO TCL_SETRESULT\fR below.  If \fIresult\fR is
\fBNULL\fR, ignores \fIfreeProc\fR and sets the result for \fIinterp\fR to

point to the empty string.
.PP
\fBTcl_GetStringResult\fR returns the result for \fIinterp\fR as a string, i.e.

the bytes of the Tcl_Obj for the result, which can be decoded using
\fBTcl_UtfToExternal\fR.  This value is freed when its corresponding Tcl_Obj is


freed.Programmers are encouraged to use the newer Tcl_Obj API procedures, e.g.

to call \fBTcl_GetObjResult\fR instead.
.PP
\fBTcl_ResetResult\fR sets the empty string as the result for \fIinterp\fR and






clears the error state managed by \fBTcl_AddErrorInfo\fR,

\fBTcl_AddObjErrorInfo\fR, and \fBTcl_SetErrorCode\fR.
.PP
\fBTcl_AppendResult\fR builds up a result from smaller pieces, appending each

\fIresult\fR in order to the current result for \fIinterp\fR.  It may be called





repeatedly as additional pieces of the result are produced, and manages the


storage for the \fIinterp\fR's result, allocating a larger result area if
necessary.  It also manages conversion to and from the \fIresult\fR field of
the \fIinterp\fR 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.
.PP
\fBTcl_TransferResult\fR transfers interpreter state from \fIsourceInterp\fR to
\fItargetInterp\fR, both of which must have been created in the same thread,



resets the result in \fIsourceInterp\fR, and moves the return options
dictionary as controlled by the return code value \fIcode\fR in the same manner
as \fBTcl_GetReturnOptions\fR.
.PP
If \fIsourceInterp\fR and \fItargetInterp\fR are the same, nothing is done.
.SH "DEPRECATED INTERFACES"
.SS "OLD STRING PROCEDURES"
.PP

The following procedures are deprecated since they manipulate the Tcl result as
a string.  Procedures such as \fBTcl_SetObjResult\fR can be significantly more

efficient.
.PP
\fBTcl_AppendElement\fR is like \fBTcl_AppendResult\fR, but it appends only one



piece, and also appends that piece as a list item.
\fBTcl_AppendElement\fR adds backslashes or braces as necessary to ensure that


\fIelement\fR is properly formatted as a list item.  Under normal conditions,
\fBTcl_AppendElement\fR adds a space character to \fIinterp\fR's result just
before adding the new list element, so that the list elements in the result are

properly separated.  However if the new list element is the first item in the
list or sublist (i.e. \fIinterp\fR's current result is empty, or consists of
the single character
.QW { ,
or ends in the characters
.QW " {" )
then no space is added.
.SH "THE TCL_FREEPROC ARGUMENT TO TCL_SETRESULT"
.PP










\fIFreeProc\fR has the following type:


















.PP
.CS
typedef void \fBTcl_FreeProc\fR(
        char *\fIblockPtr\fR);
.CE
.PP
When \fIfreeProc\fR is called, \fIblockPtr\fR is the \fIresult\fR value passed
to \fBTcl_SetResult\fR.

.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
\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)

.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







>







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







>












>






>








>






>







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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
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 "SEE ALSO"
Tcl_GetObjResult, Tcl_GetStringResult, Tcl_TraceVar

.SH KEYWORDS
array, get variable, interpreter, scalar, set, unset, value, variable







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





244
245
246
247
248
249
250
251
252
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
\fB#include <tcl.h>\fR
.sp
const char *
\fBTcl_SignalId\fR(\fIsig\fR)
.sp
const char *
\fBTcl_SignalMsg\fR(\fIsig\fR)
.sp
.SH ARGUMENTS
.AS int sig
.AP int sig in
A POSIX signal number such as \fBSIGPIPE\fR.
.BE

.SH DESCRIPTION







|







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

.SH ARGUMENTS
.AS int ms
.AP int ms in
Number of milliseconds to sleep.
.BE
.SH DESCRIPTION
.PP







>







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
'\"
'\" Copyright (c) 1998-2000 by 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)

.SH ARGUMENTS
.AS Tcl_Interp *interp
.AP Tcl_Interp *interp in
Tcl interpreter to source rc file into.
.BE

.SH DESCRIPTION

|











<

>







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

\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
.sp
int
\fBTcl_SplitList\fR(\fIinterp, list, argcPtr, argvPtr\fR)
.sp
char *
\fBTcl_Merge\fR(\fIargc, argv\fR)
.sp
size_t
\fBTcl_ScanElement\fR(\fIsrc, flagsPtr\fR)
.sp
size_t
\fBTcl_ScanCountedElement\fR(\fIsrc, length, flagsPtr\fR)
.sp
size_t
\fBTcl_ConvertElement\fR(\fIsrc, dst, flags\fR)
.sp
size_t
\fBTcl_ConvertCountedElement\fR(\fIsrc, length, dst, flags\fR)

.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
Pointer to a string with proper list structure.
.AP int *argcPtr out
Filled in with number of elements in \fIlist\fR.





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







|


|


|


|

>





|

|

>
>
>
>
>





|









|







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
Tcl_Size
\fBTcl_ScanElement\fR(\fIsrc, flagsPtr\fR)
.sp
Tcl_Size
\fBTcl_ScanCountedElement\fR(\fIsrc, length, flagsPtr\fR)
.sp
Tcl_Size
\fBTcl_ConvertElement\fR(\fIsrc, dst, flags\fR)
.sp
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 "const char" *list in
Pointer to a string with proper list structure.
.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 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 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
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

int argc, 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);
.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
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







>
|










|



|
>
|







83
84
85
86
87
88
89
90
91
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 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(argv);
.CE
.PP
\fBTcl_SplitList\fR normally returns \fBTCL_OK\fR, which means the list was
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
\fBTcl_SplitPath\fR(\fIpath, argcPtr, argvPtr\fR)
.sp
char *
\fBTcl_JoinPath\fR(\fIargc, argv, resultPtr\fR)
.sp
Tcl_PathType
\fBTcl_GetPathType\fR(\fIpath\fR)

.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
Filled in with number of path elements in \fIpath\fR.





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







>





|

>
>
>
>
>





|







16
17
18
19
20
21
22
23
24
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 "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 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
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;
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);
.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.







|










|







63
64
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
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(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
'\"
'\" Copyright (c) 2001 by 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

|







1
2
3
4
5
6
7
8
9
'\"
'\" 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
.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)
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)
All uninitialized standard channels are initialized to
platform-specific default values:
.RS
.TP
(a)
when open channels are listed with \fBTcl_GetChannelNames\fR (or the
\fBfile channels\fR script command), or
.TP
(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)
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







<
|








<
|



<
|


<
|










<
|







41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56

57
58
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.)

.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

.IP 2)
All uninitialized standard channels are initialized to
platform-specific default values:
.RS

.IP (a)
when open channels are listed with \fBTcl_GetChannelNames\fR (or the
\fBfile channels\fR script command), or

.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

.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
\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)

.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[].







>







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.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114

115
116
117
118
119
120
121





122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
.sp
Tcl_Obj *
\fBTcl_NewStringObj\fR(\fIbytes, length\fR)
.sp
Tcl_Obj *
\fBTcl_NewUnicodeObj\fR(\fIunicode, numChars\fR)
.sp
void
\fBTcl_SetStringObj\fR(\fIobjPtr, bytes, length\fR)
.sp
void
\fBTcl_SetUnicodeObj\fR(\fIobjPtr, unicode, numChars\fR)
.sp
char *
\fBTcl_GetStringFromObj\fR(\fIobjPtr, lengthPtr\fR)
.sp
char *
\fBTcl_GetString\fR(\fIobjPtr\fR)
.sp
Tcl_UniChar *
\fBTcl_GetUnicodeFromObj\fR(\fIobjPtr, lengthPtr\fR)
.sp
Tcl_UniChar *
\fBTcl_GetUnicode\fR(\fIobjPtr\fR)
.sp
int
\fBTcl_GetUniChar\fR(\fIobjPtr, index\fR)
.sp
int
\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)
.sp
void
\fBTcl_AppendLimitedToObj\fR(\fIobjPtr, bytes, length, limit, ellipsis\fR)
.sp
Tcl_Obj *
\fBTcl_Format\fR(\fIinterp, format, objc, objv\fR)
.sp
int
\fBTcl_AppendFormatToObj\fR(\fIinterp, objPtr, format, objc, objv\fR)
.sp
Tcl_Obj *
\fBTcl_ObjPrintf\fR(\fIformat, ...\fR)
.sp
void
\fBTcl_AppendPrintfToObj\fR(\fIobjPtr, format, ...\fR)
.sp
void
\fBTcl_SetObjLength\fR(\fIobjPtr, newLength\fR)
.sp
int
\fBTcl_AttemptSetObjLength\fR(\fIobjPtr, newLength\fR)
.sp
Tcl_Obj *
\fBTcl_ConcatObj\fR(\fIobjc, objv\fR)

.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
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
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.
.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
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
The index of the Unicode character to return.
.AP size_t 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
The index of the last Unicode character in the Unicode range to be
returned as a new value.

.AP Tcl_Obj *objPtr in/out
Points to a value to manipulate.
.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 "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
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
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
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







<


<

















|





<


<


<


<
|

<











<


<







>






|



|


|





|


|
|

|

|
>
|

|
>

|


|
|
|
>
>
>
>
>


<
<
<
|








|



|







15
16
17
18
19
20
21

22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

47
48

49
50

51
52

53
54

55
56
57
58
59
60
61
62
63
64
65

66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
.sp
Tcl_Obj *
\fBTcl_NewStringObj\fR(\fIbytes, length\fR)
.sp
Tcl_Obj *
\fBTcl_NewUnicodeObj\fR(\fIunicode, numChars\fR)
.sp

\fBTcl_SetStringObj\fR(\fIobjPtr, bytes, length\fR)
.sp

\fBTcl_SetUnicodeObj\fR(\fIobjPtr, unicode, numChars\fR)
.sp
char *
\fBTcl_GetStringFromObj\fR(\fIobjPtr, lengthPtr\fR)
.sp
char *
\fBTcl_GetString\fR(\fIobjPtr\fR)
.sp
Tcl_UniChar *
\fBTcl_GetUnicodeFromObj\fR(\fIobjPtr, lengthPtr\fR)
.sp
Tcl_UniChar *
\fBTcl_GetUnicode\fR(\fIobjPtr\fR)
.sp
int
\fBTcl_GetUniChar\fR(\fIobjPtr, index\fR)
.sp
Tcl_Size
\fBTcl_GetCharLength\fR(\fIobjPtr\fR)
.sp
Tcl_Obj *
\fBTcl_GetRange\fR(\fIobjPtr, first, last\fR)
.sp

\fBTcl_AppendToObj\fR(\fIobjPtr, bytes, length\fR)
.sp

\fBTcl_AppendUnicodeToObj\fR(\fIobjPtr, unicode, numChars\fR)
.sp

\fBTcl_AppendObjToObj\fR(\fIobjPtr, appendObjPtr\fR)
.sp

\fBTcl_AppendStringsToObj\fR(\fIobjPtr, string, string, ... \fBNULL\fR)
.sp

\fBTcl_AppendLimitedToObj\fR(\fIobjPtr, bytes, length, limit, ellipsis\fR)
.sp
Tcl_Obj *
\fBTcl_Format\fR(\fIinterp, format, objc, objv\fR)
.sp
int
\fBTcl_AppendFormatToObj\fR(\fIinterp, objPtr, format, objc, objv\fR)
.sp
Tcl_Obj *
\fBTcl_ObjPrintf\fR(\fIformat, ...\fR)
.sp

\fBTcl_AppendPrintfToObj\fR(\fIobjPtr, format, ...\fR)
.sp

\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 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 Tcl_Size length in
The number of bytes to copy from \fIbytes\fR when
initializing, setting, or appending to a string value.
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 Tcl_Size numChars in
The number of Unicode characters to copy from \fIunicode\fR when
initializing, setting, or appending to a string value.
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 Tcl_Size first in
The index of the first Unicode character in the Unicode range to be
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. If negative, take all characters up to
the last one available.
.AP Tcl_Obj *objPtr in/out
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 "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 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 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 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
\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;
.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.


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


.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







|
|


|
|
|
|
>
>







|





>
>







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
\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
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.  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 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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
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,
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







|







252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
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 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
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



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







|
|
>
>
>







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
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 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
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 "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







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





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

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







>









|







11
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
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
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 "SEE ALSO"
subst(n)
.SH KEYWORDS
backslash substitution, command substitution, variable substitution







>
>
>
>
>
>
>




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
'\"
'\" Copyright (c) 1992-1999 Karl Lehenbauer and Mark Diekhans.
'\" Copyright (c) 2000 by 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

|
|







1
2
3
4
5
6
7
8
9
10
'\"
'\" 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.

1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28


29
30
31
32


33
34
35
36

37







38
39


40






41
42
43
44
45
46

47


48
49
50



51
52
53
54
55
56
57
58
59
60
61
62

63

64
65
66
67

68

69
70
71
72
73
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145


146
147
148
149
150
151
152
153
154
155
156
157


158
159
160

161
162
163

164
165
166

167
168
169

170
171
172

173
174
175

176
177
178

179
180
181
182
183
184
185
186
187
188
189
190

191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

273
274
275
276
277
278
'\"
'\" 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 n "8.6" Tcl "Tcl Built-In Commands"
.so man.macros
.BS
.SH NAME
Tcl \- Tool Command Language
.SH SYNOPSIS
Summary of Tcl language syntax.
.BE
.SH DESCRIPTION
.PP
The following rules define the syntax and semantics of the Tcl language:

.IP "[1] \fBCommands.\fR"
A Tcl script is a string containing one or more commands.
Semi-colons and newlines are command separators unless quoted as
described below.
Close brackets are command terminators during command substitution
(see below) unless quoted.
.IP "[2] \fBEvaluation.\fR"
A command is evaluated in two steps.
First, the Tcl interpreter breaks the command into \fIwords\fR
and performs substitutions as described below.


These substitutions are performed in the same way for all
commands.
Secondly, the first word is used to locate a routine to
carry out the command, and the remaining words of the command are


passed to that routine.
The routine is free to interpret each of its words
in any way it likes, such as an integer, variable name, list,
or Tcl script.

Different commands interpret their words differently.







.IP "[3] \fBWords.\fR"
Words of a command are separated by white space (except for


newlines, which are command separators).






.IP "[4] \fBDouble quotes.\fR"
If the first character of a word is double-quote
.PQ \N'34'
then the word is terminated by the next double-quote character.
If semi-colons, close brackets, or white space characters
(including newlines) appear between the quotes then they are treated

as ordinary characters and included in the word.


Command substitution, variable substitution, and backslash substitution
are performed on the characters between the quotes as described below.
The double-quotes are not retained as part of the word.



.IP "[5] \fBArgument expansion.\fR"
If a word starts with the string
.QW {*}
followed by a non-whitespace character, then the leading
.QW {*}
is removed and the rest of the word is parsed and substituted as any other
word. After substitution, the word is parsed as a list (without command or
variable substitutions; backslash substitutions are performed as is normal for
a list and individual internal words may be surrounded by either braces or
double-quote characters), and its words are added to the command being
substituted. For instance,
.QW "cmd a {*}{b [c]} d {*}{$e f {g h}}"

is equivalent to

.QW "cmd a b {[c]} d {$e} f {g h}" .
.IP "[6] \fBBraces.\fR"
If the first character of a word is an open brace
.PQ {

and rule [5] does not apply, then

the word is terminated by the matching close brace
.PQ } "" .
Braces nest within the word: for each additional open
brace there must be an additional close brace (however,
if an open brace or close brace within the word is
quoted with a backslash then it is not counted in locating the
matching close brace).
No substitutions are performed on the characters between the
braces except for backslash-newline substitutions described
below, nor do semi-colons, newlines, close brackets,
or white space receive any special interpretation.
The word will consist of exactly the characters between the
outer braces, not including the braces themselves.

.IP "[7] \fBCommand substitution.\fR"
If a word contains an open bracket
.PQ [
then Tcl performs \fIcommand substitution\fR.
To do this it invokes the Tcl interpreter recursively to process
the characters following the open bracket as a Tcl script.
The script may contain any number of commands and must be terminated
by a close bracket
.PQ ] "" .
The result of the script (i.e. the result of its last command) is
substituted into the word in place of the brackets and all of the
characters between them.
There may be any number of command substitutions in a single word.
Command substitution is not performed on words enclosed in braces.
.IP "[8] \fBVariable substitution.\fR"
If a word contains a dollar-sign
.PQ $
followed by one of the forms
described below, then Tcl performs \fIvariable
substitution\fR:  the dollar-sign and the following characters are


replaced in the word by the value of a variable.
Variable substitution may take any of the following forms:
.RS
.TP 15
\fB$\fIname\fR
.
\fIName\fR is the name of a scalar variable;  the name is a sequence
of one or more characters that are a letter, digit, underscore,
or namespace separators (two or more colons).
Letters and digits are \fIonly\fR the standard ASCII ones (\fB0\fR\(en\fB9\fR,
\fBA\fR\(en\fBZ\fR and \fBa\fR\(en\fBz\fR).
.TP 15
\fB$\fIname\fB(\fIindex\fB)\fR
.
\fIName\fR gives the name of an array variable and \fIindex\fR gives
the name of an element within that array.
\fIName\fR must contain only letters, digits, underscores, and
namespace separators, and may be an empty string.
Letters and digits are \fIonly\fR the standard ASCII ones (\fB0\fR\(en\fB9\fR,
\fBA\fR\(en\fBZ\fR and \fBa\fR\(en\fBz\fR).
Command substitutions, variable substitutions, and backslash
substitutions are performed on the characters of \fIindex\fR.
.TP 15
\fB${\fIname\fB}\fR
.
\fIName\fR is the name of a scalar variable or array element.  It may contain
any characters whatsoever except for close braces.  It indicates an array
element if \fIname\fR is in the form
.QW \fIarrayName\fB(\fIindex\fB)\fR
where \fIarrayName\fR does not contain any open parenthesis characters,
.QW \fB(\fR ,
or close brace characters,
.QW \fB}\fR ,
and \fIindex\fR can be any sequence of characters except for close brace
characters.  No further

substitutions are performed during the parsing of \fIname\fR.
.PP
There may be any number of variable substitutions in a single word.
Variable substitution is not performed on words enclosed in braces.
.PP
Note that variables may contain character sequences other than those listed
above, but in that case other mechanisms must be used to access them (e.g.,
via the \fBset\fR command's single-argument form).
.RE


.IP "[9] \fBBackslash substitution.\fR"
If a backslash
.PQ \e
appears within a word then \fIbackslash substitution\fR occurs.
In all cases but those described below the backslash is dropped and
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
.TP 7
\e\fBa\fR

Audible alert (bell) (Unicode U+000007).
.TP 7
\e\fBb\fR

Backspace (Unicode U+000008).
.TP 7
\e\fBf\fR

Form feed (Unicode U+00000C).
.TP 7
\e\fBn\fR

Newline (Unicode U+00000A).
.TP 7
\e\fBr\fR

Carriage-return (Unicode U+00000D).
.TP 7
\e\fBt\fR

Tab (Unicode U+000009).
.TP 7
\e\fBv\fR

Vertical tab (Unicode U+00000B).
.TP 7
\e\fB<newline>\fIwhiteSpace\fR
.
A single space character replaces the backslash, newline, and all spaces
and tabs after the newline.  This backslash sequence is unique in that it
is replaced in a separate pre-pass before the command is actually parsed.
This means that it will be replaced even when it occurs between braces,
and the resulting space will be treated as a word separator if it is not
in braces or quotes.
.TP 7
\e\e

Backslash
.PQ \e "" .
.TP 7
\e\fIooo\fR
.
The digits \fIooo\fR (one, two, or three of them) give a eight-bit octal
value for the Unicode character that will be inserted, in the range
\fI000\fR\(en\fI377\fR (i.e., the range U+000000\(enU+0000FF).
The parser will stop just before this range overflows, or when
the maximum of three digits is reached.  The upper bits of the Unicode
character will be 0.
.TP 7
\e\fBx\fIhh\fR
.
The hexadecimal digits \fIhh\fR (one or two of them) give an eight-bit
hexadecimal value for the Unicode character that will be inserted.  The upper
bits of the Unicode character will be 0 (i.e., the character will be in the
range U+000000\(enU+0000FF).
.TP 7
\e\fBu\fIhhhh\fR
.
The hexadecimal digits \fIhhhh\fR (one, two, three, or four of them) give a
sixteen-bit hexadecimal value for the Unicode character that will be
inserted.  The upper bits of the Unicode character will be 0 (i.e., the
character will be in the range U+000000\(enU+00FFFF).
.TP 7
\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
.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
.PQ #
appears at a point where Tcl is
expecting the first character of the first word of a command,
then the hash character and the characters that follow it, up
through the next newline, are treated as a comment and ignored.
The comment character only has significance when it appears
at the beginning of a command.
.IP "[11] \fBOrder of substitution.\fR"
Each character is processed exactly once by the Tcl interpreter
as part of creating the words of a command.
For example, if variable substitution occurs then no further
substitutions are performed on the value of the variable;  the
value is inserted into the word verbatim.
If command substitution occurs then the nested command is
processed entirely by the recursive call to the Tcl interpreter;
no substitutions are performed before making the recursive
call and no additional substitutions are performed on the result
of the nested script.
.RS
.PP
Substitutions take place from left to right, and each substitution is
evaluated completely before attempting to evaluate the next.  Thus, a
sequence like
.PP
.CS
set y [set x 0][incr x][incr x]
.CE
.PP
will always set the variable \fIy\fR to the value, \fI012\fR.
.RE
.IP "[12] \fBSubstitution and word boundaries.\fR"
Substitutions do not affect the word boundaries of a command,
except for argument expansion as specified in rule [5].
For example, during variable substitution the entire value of
the variable becomes part of a single word, even if the variable's
value contains spaces.

.SH KEYWORDS
backslash, command, comment, script, substitution, variable
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:



>















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

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

<
<
|
<
|
|
|
|
|
>

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

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

|
|
<
>
>
|
<




|
<
<
<
<



<
<
<
<
<
<
<
|



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

>
>
|
|

<
|
<
|
|
<
<
|
|
>
>



>
|


>
|


>
|


>
|


>
|


>
|


>
|



|
|
|
<
|
|


>





<
|
|
|
<
<



|
<
<
|



|
<
<
|



|
<
|
|
<
<
<
<
<
<
<

<
<
<

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

<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
>






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23



24
25

26
27
28
29
30

31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65


66
67
68
69
70
71


72

73
74
75
76
77
78
79
80
81


82
83
84
85
86

87
88
89






90

91
92
93
94
95




96
97




98
99
100
101
102

103
104
105

106
107
108
109
110




111
112
113







114
115
116
117


118


119

120


121
122







123
124
125
126
127
128

129

130
131


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
178
179
180

181
182
183


184
185
186
187


188
189
190
191
192


193
194
195
196
197

198
199







200



201





















202









203






204
205
206
207
208
209
210
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2023 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 n "8.6" Tcl "Tcl Built-In Commands"
.so man.macros
.BS
.SH NAME
Tcl \- Tool Command Language
.SH SYNOPSIS
Summary of Tcl language syntax.
.BE
.SH DESCRIPTION
.PP
The following rules define the syntax and semantics of the Tcl language:
.
.IP "[1] \fBScript.\fR"
A script is composed of zero or more commands delimited by semi-colons or
newlines.



.IP "[2] \fBCommand.\fR"
A command is composed of zero or more words delimited by whitespace.  The

replacement for a substitution is included verbatim in the word. For example, a
space in the replacement is included in the word rather than becoming a
delimiter, and \fI\\\\\fR becomes a single backslash in the word.  Each word is
processed from left to right and each substitution is performed as soon as it
is complete.

For example, the command
.RS
.PP
.CS
set y [set x 0][incr x][incr x]

.CE
.PP
is composed of three words, and sets the value of \fIy\fR to \fI012\fR.
.PP
If hash
.PQ #
is the first character of what would otherwise be the first word of a command,
all characters up to the next newline are ignored.
.RE
.
.IP "[3] \fBBraced word.\fR"

If a word is enclosed in braces
.PQ {
and
.PQ } ""
, the braces are removed and the enclosed characters become the word.  No
substitutions are performed.  Nested pairs of braces may occur within the word.
A brace preceded by an odd number of backslashes is not considered part of a
pair, and neither brace nor the backslashes are removed from the word.
.
.IP "[4] \fBQuoted word.\fR"
If a word is enclosed in double quotes
.PQ \N'34'
, the double quotes are removed and the enclosed characters become the word.

Substitutions are performed.
.
.IP "[5] \fBList.\fR"
A list has the form of a single command.  Newline is whitespace, and semicolon
has no special interpretation.  There is no script evaluation so there is no
argument expansion, variable substitution, or command substitution: Dollar-sign


and open bracket have no special interpretation, and what would be argument
expansion in a script is invalid in a list.
.
.IP "[6] \fBArgument expansion.\fR"
If
.QW {*}


prefixes a word, it is removed.  After any remaining enclosing braces or quotes

are processed and applicable substitutions performed, the word, which must
be a list, is removed from the command, and in its place each word in the
list becomes an additional word in the command.  For example,
.CS
cmd a {*}{b [c]} d {*}{$e f {g h}}
.CE
is equivalent to
.CS
cmd a b {[c]} d {$e} f {g h} .


.CE
.
.IP "[7] \fBEvaluation.\fR"
To evaluate a script, an interpreter evaluates each successive command.  The
first word identifies a procedure, and the remaining words are passed to that

procedure for further evaluation.  The procedure interprets each argument in
its own way, e.g. as an integer, variable name, list, mathematical expression,
script, or in some other arbitrary way.  The result of the last command is the






result of the script.

.
.IP "[8] \fBCommand substitution.\fR"
Each pair of brackets
.PQ [
and




.PQ ] ""
encloses a script and is replaced by the result of that script.




.IP "[9] \fBVariable substitution.\fR"
Each of the following forms begins with dollar sign
.PQ $
and is replaced by the value of the identified variable.  \fIname\fR names the
variable and is composed of ASCII letters (\fBA\fR\(en\fBZ\fR and

\fBa\fR\(en\fBz\fR), digits (\fB0\fR\(en\fB9\fR), underscores, or namespace
delimiters (two or more colons).  \fIindex\fR is the name of an individual
variable within an array variable, and may be empty.

.RS
.TP 15
\fB$\fIname\fR
.
\fIname\fR may not be empty.




.TP 15
\fB$\fIname\fB(\fIindex\fB)\fR
.







\fIname\fR may be empty.  Substitutions are performed on \fIindex\fR.
.TP 15
\fB${\fIname\fB}\fR
.


\fIname\fR may be empty.


.TP 15

\fB${\fIname(index)\fB}\fR


.
\fIname\fR may be empty. No substitutions are performed.







.RE
Variables that are not accessible through one of the forms above may be
accessed through other mechanisms, e.g. the \fBset\fR command.
.IP "[10] \fBBackslash substitution.\fR"
Each backslash
.PQ \e

that is not part of one of the forms listed below is removed, and the next

character is included in the word verbatim, which allows the inclusion of
characters that would normally be interpreted, namely whitespace, braces,


brackets, double quote, dollar sign, and backslash.  The following sequences
are replaced as described:
.RS
.RS
.RS
.TP 7
\e\fBa\fR
.
Audible alert (bell) (U+7).
.TP 7
\e\fBb\fR
.
Backspace (U+8).
.TP 7
\e\fBf\fR
.
Form feed (U+C).
.TP 7
\e\fBn\fR
.
Newline (U+A).
.TP 7
\e\fBr\fR
.
Carriage-return (U+D).
.TP 7
\e\fBt\fR
.
Tab (U+9).
.TP 7
\e\fBv\fR
.
Vertical tab (U+B).
.TP 7
\e\fB<newline>\fIwhiteSpace\fR
.
Newline preceded by an odd number of backslashes, along with the consecutive
spaces and tabs that immediately follow it, is replaced by a single space.
Because this happens before the command is split into words, it occurs even

within braced words, and if the resulting space may subsequently be treated as
a word delimiter.
.TP 7
\e\e
.
Backslash
.PQ \e "" .
.TP 7
\e\fIooo\fR
.

Up to three octal digits form an eight-bit value for a Unicode character in the
range \fI0\fR\(en\fI377\fR, i.e. U+0\(enU+FF.  Only the digits that result in a
number in this range are consumed.


.TP 7
\e\fBx\fIhh\fR
.
Up to two hexadecimal digits form an eight-bit value for a Unicode character in


the range \fI0\fR\(en\fIFF\fR.
.TP 7
\e\fBu\fIhhhh\fR
.
Up to four hexadecimal digits form a 16-bit value for a Unicode character in


the range \fI0\fR\(en\fIFFFF\fR.
.TP 7
\e\fBU\fIhhhhhhhh\fR
.
Up to eight hexadecimal digits form a 21-bit value for a Unicode character in

the range \fI0\fR\(en\fI10FFFF\fR.  Only the digits that result in a number in
this range are consumed.







.RE



.RE





















.PP









.RE






.
.SH KEYWORDS
backslash, command, comment, script, substitution, variable
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/TclZlib.3.

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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 "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
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
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







|


















|
|







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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 "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 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 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
\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
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







|







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
\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 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
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
.
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
.
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
.
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
.
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
.
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
.
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
.
The type of the uncompressed data (either \fBbinary\fR or \fBtext\fR) if
known.

























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







<
|
<


<
|
<


<
|
<



<
|
<






<
|
<



<
|
<




<
|
<


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












215
216
217
218
219
220
221

222

223
224

225

226
227

228

229
230
231

232

233
234
235
236
237
238

239

240
241
242

243

244
245
246
247

248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
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.

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

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

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

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

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

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

.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
'\"
'\" 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"
.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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
\fBTcl_Main\fR(\fIargc, argv, appInitProc\fR)
.sp




\fBTcl_SetStartupScript\fR(\fIpath, encoding\fR)
.sp
Tcl_Obj *
\fBTcl_GetStartupScript\fR(\fIencodingPtr\fR)
.sp
\fBTcl_SetMainLoop\fR(\fImainLoopProc\fR)

.SH ARGUMENTS
.AS Tcl_MainLoopProc *mainLoopProc
.AP int 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 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.


.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








|



|






>
>
>
>






>


|




>
>
>
>












>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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 9.0 Tcl "Tcl Library Procedures"
.so man.macros
.BS
.SH NAME
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 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
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.
.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







|
>
>
|







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














.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







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





200
201
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
.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 *
\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)

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







<


<


<


|


<


<


<







>







10
11
12
13
14
15
16

17
18

19
20

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

\fBTcl_ConditionNotify\fR(\fIcondPtr\fR)
.sp

\fBTcl_ConditionWait\fR(\fIcondPtr, mutexPtr, timePtr\fR)
.sp

\fBTcl_ConditionFinalize\fR(\fIcondPtr\fR)
.sp
void *
\fBTcl_GetThreadData\fR(\fIkeyPtr, size\fR)
.sp

\fBTcl_MutexLock\fR(\fImutexPtr\fR)
.sp

\fBTcl_MutexUnlock\fR(\fImutexPtr\fR)
.sp

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







|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
.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 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.

Changes to doc/ToUpper.3.

1
2
3
4
5
6
7
8
9
'\"
'\" Copyright (c) 1997 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.
'\"
.TH Tcl_UtfToUpper 3 "8.1" Tcl "Tcl Library Procedures"
.so man.macros
.BS

|







1
2
3
4
5
6
7
8
9
'\"
'\" 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
.sp
int
\fBTcl_UniCharToLower\fR(\fIch\fR)
.sp
int
\fBTcl_UniCharToTitle\fR(\fIch\fR)
.sp
int
\fBTcl_UtfToUpper\fR(\fIstr\fR)
.sp
int
\fBTcl_UtfToLower\fR(\fIstr\fR)
.sp
int
\fBTcl_UtfToTitle\fR(\fIstr\fR)

.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







|


|


|

>







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
Tcl_Size
\fBTcl_UtfToUpper\fR(\fIstr\fR)
.sp
Tcl_Size
\fBTcl_UtfToLower\fR(\fIstr\fR)
.sp
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
.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
.sp
int
\fBTcl_TraceCommand(\fIinterp, cmdName, flags, proc, clientData\fB)\fR
.sp
void
\fBTcl_UntraceCommand(\fIinterp, cmdName, flags, proc, clientData\fB)\fR

.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







|


|

<
|
>







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\fR(\fIinterp, cmdName, flags, proc, prevClientData\fR)
.sp
int
\fBTcl_TraceCommand\fR(\fIinterp, cmdName, flags, proc, clientData\fR)
.sp

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







>



>







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
.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
.sp
int
\fBTcl_TraceVar2(\fIinterp, name1, name2, flags, proc, clientData\fB)\fR
.sp
\fBTcl_UntraceVar(\fIinterp, varName, flags, proc, clientData\fB)\fR
.sp
\fBTcl_UntraceVar2(\fIinterp, name1, name2, flags, proc, clientData\fB)\fR
.sp
void *
\fBTcl_VarTraceInfo(\fIinterp, varName, flags, proc, prevClientData\fB)\fR
.sp
void *
\fBTcl_VarTraceInfo2(\fIinterp, name1, name2, flags, proc, prevClientData\fB)\fR

.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







|


|

|

|


|


|
>







11
12
13
14
15
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\fR(\fIinterp, varName, flags, proc, clientData\fR)
.sp
int
\fBTcl_TraceVar2\fR(\fIinterp, name1, name2, flags, proc, clientData\fR)
.sp
\fBTcl_UntraceVar\fR(\fIinterp, varName, flags, proc, clientData\fR)
.sp
\fBTcl_UntraceVar2\fR(\fIinterp, name1, name2, flags, proc, clientData\fR)
.sp
void *
\fBTcl_VarTraceInfo\fR(\fIinterp, varName, flags, proc, prevClientData\fR)
.sp
void *
\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
.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,
        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).


\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







>





>





>



>



>







>






>






>















|
|









|
|
|
>
>







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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,
        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 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
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 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







>
>
>
>
>
>
>
>








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
'\"
'\" 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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
char *
\fBTcl_TranslateFileName\fR(\fIinterp\fR, \fIname\fR, \fIbufferPtr\fR)

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











|






>





|
<











|










|







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

26
27
28
29
30
31
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
.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

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







|
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, 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
\fBTcl_UniCharIsSpace\fR(\fIch\fR)
.sp
int
\fBTcl_UniCharIsUpper\fR(\fIch\fR)
.sp
int
\fBTcl_UniCharIsWordChar\fR(\fIch\fR)

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

.PP
\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.

.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







>
















|
>

|
>





|
>







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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.
.PP
\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.
.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
.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
.sp
int
\fBTcl_UpVar2(\fIinterp, frameName, name1, name2, destName, flags\fB)\fR

.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







|


|
>







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\fR(\fIinterp, frameName, sourceName, destName, flags\fR)
.sp
int
\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
'\"
'\" 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
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
.sp
typedef ... \fBTcl_UniChar\fR;
.sp
int
\fBTcl_UniCharToUtf\fR(\fIch, buf\fR)
.sp
int
\fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR)
.sp
int
\fBTcl_UtfToChar16\fR(\fIsrc, uPtr\fR)
.sp
int
\fBTcl_UtfToWChar\fR(\fIsrc, wPtr\fR)
.sp
char *
\fBTcl_UniCharToUtfDString\fR(\fIuniStr, uniLength, dsPtr\fR)
.sp
char *
\fBTcl_Char16ToUtfDString\fR(\fIuStr, uniLength, dsPtr\fR)
.sp
char *
\fBTcl_WCharToUtfDString\fR(\fIwStr, uniLength, dsPtr\fR)
.sp
Tcl_UniChar *
\fBTcl_UtfToUniCharDString\fR(\fIsrc, length, dsPtr\fR)
.sp
unsigned short *
\fBTcl_UtfToChar16DString\fR(\fIsrc, length, dsPtr\fR)
.sp
wchar_t *
\fBTcl_UtfToWCharDString\fR(\fIsrc, length, dsPtr\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)
.sp
int
\fBTcl_NumUtfChars\fR(\fIsrc, length\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
\fBTcl_UtfBackslash\fR(\fIsrc, readPtr, dst\fR)

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

.AP "const Tcl_UniChar" *ucs in
A null-terminated Unicode string.
.AP "const Tcl_UniChar" *uct in
A null-terminated Unicode string.
.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.
.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.

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










|






|


|


|


|



|


|


|


|


|


|
>
>
>
>
>
>




















|


|



















|

>




















|
>

|

|

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




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

132
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_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
Tcl_Size
\fBTcl_UniCharToUtf\fR(\fIch, buf\fR)
.sp
Tcl_Size
\fBTcl_UtfToUniChar\fR(\fIsrc, chPtr\fR)
.sp
Tcl_Size
\fBTcl_UtfToChar16\fR(\fIsrc, uPtr\fR)
.sp
Tcl_Size
\fBTcl_UtfToWChar\fR(\fIsrc, wPtr\fR)
.sp
char *
\fBTcl_UniCharToUtfDString\fR(\fIuniStr, numUniChars, dsPtr\fR)
.sp
char *
\fBTcl_Char16ToUtfDString\fR(\fIutf16, numUtf16, dsPtr\fR)
.sp
char *
\fBTcl_WCharToUtfDString\fR(\fIwcharStr, numWChars, dsPtr\fR)
.sp
Tcl_UniChar *
\fBTcl_UtfToUniCharDString\fR(\fIsrc, numBytes, dsPtr\fR)
.sp
unsigned short *
\fBTcl_UtfToChar16DString\fR(\fIsrc, numBytes, dsPtr\fR)
.sp
wchar_t *
\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, numBytes\fR)
.sp
int
\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
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 sequence of \fBTcl_UniChar\fR units with null-termination optional
depending on function.
.AP "const Tcl_UniChar" *ucs in
A null-terminated sequence of \fBTcl_UniChar\fR.
.AP "const Tcl_UniChar" *uct in
A null-terminated sequence of \fBTcl_UniChar\fR.
.AP "const Tcl_UniChar" *uniPattern in
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

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 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
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
though knowing it's an illegal code-point on its own), just call
\fBTcl_UniCharToUtf\fR again specifying ch = -1.

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
















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







|
>
|
|
<
|
>














|
>
|
|
<
<

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







167
168
169
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197


198
199
200
201




202


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

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


.PP
\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.




The return value is a pointer to the appended result which is also


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

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







|
|
|
|
|




















|
>
















|




|





|
<




|







248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 \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. \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 - 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[-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 negative 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 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
.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)

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







>





|







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 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
.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
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 "SEE ALSO"
Tcl_GetIndexFromObj(3)
.SH KEYWORDS
command, error message, wrong number of arguments







|









>
>
>
>
>
>




60
61
62
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
\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
.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

\fBoo::abstract\fI method \fR?\fIarg ...\fR?
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
   \(-> \fBoo::class\fR







|







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

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

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

.TP
\fBafter \fIms\fR
.
\fIMs\fR must be an integer giving a time in milliseconds.

The command sleeps for \fIms\fR milliseconds and then returns.
While the command is sleeping the application does not respond to
events.

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




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

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

.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







>

<

<

<

<

<

>






>




>



>
















>
>
>
>


















>













>







8
9
10
11
12
13
14
15
16

17

18

19

20

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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

\fBafter \fIms \fR?\fIscript script script ...\fR?

\fBafter cancel \fIid\fR

\fBafter cancel \fIscript script script ...\fR

\fBafter idle \fR?\fIscript script script ...\fR?

\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
(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:
.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"
    }
    lassign $fun argList body ns
    set name ::$ns::[getGloballyUniqueName]
    set body0 {
         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







|





|




|







40
41
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 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"
    }
    lassign $fun argList body ns
    set name ::$ns::[getGloballyUniqueName]
    set body0 {
        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

Changes to doc/array.n.

19
20
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 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:

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

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







>


>










>







19
20
21
22
23
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 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
.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

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

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

.TP
\fBarray for {\fIkeyVariable valueVariable\fB} \fIarrayName body\fP

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.

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

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

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

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

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

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

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

.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







>


>





>


>


>


>







>


>














>


>












>


>









>


>









>


>



>


>














>


>




>


>







81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
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
.
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.
.\" 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
'\"
'\" Copyright (c) 1997 by Sun Microsystems, Inc.
'\" Copyright (c) 2008 by 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

|
|







1
2
3
4
5
6
7
8
9
10
'\"
'\" 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
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"


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

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

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

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


.RS
.PP
No options are supported during encoding. During decoding, the following
options are supported:

.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):

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

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

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

.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







>
>




|
>
|










>





>









>











|
>
>




>
















>






>











>












>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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 \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 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
.PP
which returns a binary string equivalent to:
.PP
.CS
\fB\e254\fR
.CE
.PP
(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







|







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
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
.CS
\fBbinary format\fR B5B* 11100 111000011010
.CE
.PP
will return a binary string equivalent to:
.PP
.CS
\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 .







|







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







|














|







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
.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
.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
.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
.CE
.PP
whereas:
.PP
.CS
\fBbinary format\fR c {2 5}
.CE







|







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







|















|







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







|















|







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







|







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







|







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
.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
will return
.PP
.CS
\fBabfdeghi\e000\e000j\fR
.CE
.RE
.SH "BINARY 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.


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







>



<
<
|
>
>







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







>
>
>
>
>
>
>
>
>














|







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







|













|







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







|















|







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







|














|







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







|







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







|







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
.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
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]
.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:







|









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

\fBcallback\fR \fImethodName\fR ?\fIarg ...\fR?
\fBmymethod\fR \fImethodName\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,







|

|
|







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 tcl::oo

\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/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
.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.

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
.CE
.PP
Change to the directory \fBlib\fR that is a sibling directory of the
current one:
.PP
.CS
\fBcd\fR ../lib







>








|







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

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37



38
39
40
41
42
43
44
45
46
47
48
49



50
51
52
53
54
55
56
57

58
59
60
61

62

63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84




85





86

87
88

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114





115
116
117
118





119
120
121
122
123
124
125
126
127
128
129



130
131
132
133
134
135
136
137
138
139
140
141
142
143




144
145






146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192

193
194










195


196
197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

244
245
246
247




248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
'\"
'\" Copyright (c) 2005-2006 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 chan n 8.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
chan \- Read, write and manipulate channels
.SH SYNOPSIS
\fBchan \fIoption\fR ?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
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:

.TP
\fBchan blocked \fIchannelId\fR
.
This tests whether the last input operation on the channel called
\fIchannelId\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.
.TP
\fBchan close \fIchannelId\fR ?\fIdirection\fR?
.
Close and destroy the channel called \fIchannelId\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
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

\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
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.
.PP
Channels are automatically fully closed when an interpreter is destroyed and
when the process exits.  Channels are switched to blocking mode, to
ensure that all output is correctly flushed before the process exits.
.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, \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.
.RE

.TP
\fBchan configure \fIchannelId\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?...
.
Query or set the configuration options of the channel named
\fIchannelId\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.
.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 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).
.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 \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.
.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 a number of no more than one




million, allowing buffers of up to one million bytes in size.
.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
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 \fBchan gets\fR and \fBchan read\fR) the Tcl I/O system
automatically translates the external end-of-line representation into
newline characters.  Upon output (i.e., with \fBchan puts\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.
.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
.RE

.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
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.
.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,
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
\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
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
automatically.  However, it is necessary to enter the event loop by
using the \fBvwait\fR command or by using Tk.
.PP

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
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.
.PP
Note that \fIinputChan\fR can become readable during a background
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

.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

.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 .
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
\fBrefchan\fR manual page. Command resolution happens at the
time of the call. Renaming the command, or destroying it means that
the next call of a handler method may fail, causing the channel
command invoking the handler to fail as well. Depending on the

subcommand being invoked, the error message may not be able to explain
the reason for that failure.
.PP
Every channel created with this subcommand knows which interpreter it
was created in, and only ever executes its handler command in that
interpreter, even if the channel was shared with and/or was moved into
a different interpreter. Each reflected channel also knows the thread
it was created in, and executes its handler command only in that
thread, even if the channel was moved into a different thread. To this
end all invocations of the handler are forwarded to the original
thread by posting special events to it. This means that the original
thread (i.e. the thread that executed the \fBchan create\fR command)
must have an active event loop, i.e. it must be able to process such

events. Otherwise the thread sending them will \fIblock
indefinitely\fR. Deadlock may occur.
.PP
Note that this permits the creation of a channel whose two endpoints
live in two different threads, providing a stream-oriented bridge
between these threads. In other words, we can provide a way for
regular stream communication between threads instead of having to send
commands.
.PP
When a thread or interpreter is deleted, all channels created with
this subcommand and using this thread/interpreter as their computing
base are deleted as well, in all interpreters they have been shared
with or moved into, and in whatever thread they have been transferred
to. While this pulls the rug out under the other thread(s) and/or







interpreter(s), this cannot be avoided. Trying to use such a channel
will cause the generation of a regular error about unknown channel
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
.TP
\fBchan eof \fIchannelId\fR
.
Test whether the last input operation on the channel called
\fIchannelId\fR failed because the end of the data stream was reached,
returning 1 if end-of-file was reached, and 0 otherwise.

.TP
\fBchan event \fIchannelId 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
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" .

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
special case where the most recent attempt to read from the channel
was a \fBchan gets\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 non-blocking 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.
Note that client sockets opened in asynchronous mode become writable
when they become connected or if the connection fails.
.PP
Event-driven I/O works best for channels that have been placed into
non-blocking mode with the \fBchan configure\fR command.  In blocking
mode, a \fBchan puts\fR command may block if you give it more data
than the underlying file or device can accept, and a \fBchan gets\fR
or \fBchan read\fR command will block if you attempt to read more data
than is ready; no events will be processed while the commands block.
In non-blocking mode \fBchan puts\fR, \fBchan read\fR, and \fBchan
gets\fR never block.
.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 \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

.TP
\fBchan flush \fIchannelId\fR
.
Ensures that all pending output for the channel called \fIchannelId\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
.TP
\fBchan gets \fIchannelId\fR ?\fIvarName\fR?
.
Reads the next line from the channel called \fIchannelId\fR. If
\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.
.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.

.RE

.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.
.TP
\fBchan pending \fImode channelId\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
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.


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

.TP
\fBchan postevent \fIchannelId 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
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
were created/opened by \fBchan create\fR. All other channels will
cause this subcommand to report an error.





.PP
As only the Tcl level of a channel, i.e. its command handler, should
post events to it we also restrict the usage of this command to the
interpreter that created the channel. In other words, posting events

to a reflected channel from an interpreter that does not contain it's
implementation is not allowed. Attempting to post an event from any
other interpreter will cause this subcommand to report an error.

.PP
Another restriction is that it is not possible to post events that the
I/O core has not registered an interest in. Trying to do so will cause
the method to throw an error. See the command handler method
\fBwatch\fR described in \fBrefchan\fR, the document specifying
the API of command handlers for reflected channels.
.PP
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

.TP
\fBchan push \fIchannelId cmdPrefix\fR

Adds a new transformation on top of the channel \fIchannelId\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.
.TP
\fBchan puts\fR ?\fB\-nonewline\fR? ?\fIchannelId\fR? \fIstring\fR
.
Writes \fIstring\fR to the channel named \fIchannelId\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
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
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).
.RE

.TP
\fBchan read \fIchannelId\fR ?\fInumChars\fR?
.TP
\fBchan read \fR?\fB\-nonewline\fR? \fIchannelId\fR
.
In the first form, the result will be the next \fInumChars\fR
characters read from the channel named \fIchannelId\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
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.
.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
.
In this form \fBchan read\fR blocks until \fInumChars\fR have been
received from the serial port.
.TP
\fBchan read \fIchannelId\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.
.RE

.TP
\fBchan seek \fIchannelId 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
\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
.
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
\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

.TP
\fBchan tell \fIchannelId\fR
.
Returns a number giving the current access position within the
underlying data stream for the channel named \fIchannelId\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.

.TP
\fBchan truncate \fIchannelId\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
offset within the underlying data stream if \fIlength\fR is
omitted). The channel is flushed before truncation.
.
.SH EXAMPLES

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


>








|

|



|
|
<
|
|
|
|
>

|

|
|
|
|
|
<

|

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

<
<
>
|
|
<

>
|
>
|
>

<
<
<
|
<
|
|
<
<

<
|
|

<
<
|
|
>

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

>

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

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

|

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

|

|
|
|
>
>
>
>
|

>
>
>
>
>
>
|

|
|
|
<
<
|
<
|
<
<


<
<
<
|
<
|
<
<

|
|
|

<
|

|

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

|

|

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


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


>



|
|
|
<
|
|


<
<
<
|
<
<
<
<
<

<
|
|
<
|
|
<
|
|
<
|

>
|
|
>
>
>
|
<
|
|

|
<
|
|
|
>


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

>



|
<
|
<
|
<
<
<


<
<
|


|
|
<
|
<

|
<
|
<
<
<
>
|
<

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

|
|
<
|
|

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

<
|
|
>

|

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


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

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

>
|
|
<
|
|

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

>

|

<
<
<
<
|
<
|
|
<
|
<

|

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


<
|
|
|
<
|
>

>



|
|
|

|

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


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


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

|

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

|
<
|
>
|
|
<
>

<
<
|
|
<

<
|
<
|
<
|

>

|
>
|
<
|
|
|
|
|
<

|

|
|
<
<



|
<
|
<
<
<

|
|
|
<
<
>

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

>

|

|

|
<
|
|
|
|
|
<


|
<
<
|
<
|
|
|
|

|
|
<
<

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

>

|

|
|
|
|

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

<
<
|
<
|
<
|

|
|
|

>

|

<
|
|
|
<
<
>

|

|
|
<
<


>

|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

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

33
34
35
36
37
38
39
40
41
42
43





44


45
46
47
48
49
50
51
52

53


54
55
56

57
58
59
60
61
62
63



64

65
66


67

68
69
70


71
72
73
74

75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91






















92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108



109
110
111
112
113
114
115
116
117
118


119




120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142


143

144


145
146



147

148


149
150
151
152
153

154
155
156
157


158

159

160







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

184
185

186
187
188
189
190

191
192
193
194
195
196
197
198
199
200



201

202


203
204


205
206
207


208

209

210

211
212
213
214
215

216
217
218
219
220

221
222

223
224

225

226
227
228
229


230

231

232

233
234
235
236
237
238
239
240
241
242
243

244
245
246
247



248





249

250
251

252
253

254
255

256
257
258
259
260
261
262
263
264

265
266
267
268

269
270
271
272
273
274























275
276
277
278
279
280

281

282



283
284


285
286
287
288
289

290

291
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
'\"
'\" Copyright (c) 2005-2006 Donal K. Fellows
'\" Copyright (c) 2021 Nathan Coulter
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
.TH chan n 8.5 Tcl "Tcl Built-In Commands"
.so man.macros
.BS
'\" Note:  do not modify the .SH NAME line immediately below!
.SH NAME
chan \- Reads, writes and manipulates channels.
.SH SYNOPSIS
\fBchan \fIoperation\fR ?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
\fBchan\fR provides several operations for reading from, writing to, and
otherwise manipulating channels, e.g. those created by \fBopen\fR and

\fBsocket\fR, or the default channels \fBstdin\fR, \fBstdout\fR or \fBstderr\fR
which correspond respectively to the standard input, output, and error streams
of the process.  Any unique abbreviation for \fIoperation\fR is acceptable.
Available operations are:
.\" METHOD: blocked
.TP
\fBchan blocked \fIchannelName\fR
.
Returns 1 when the channel is in non-blocking mode and the last input operation
on the channel failed because it would have otherwise caused the process to
block, and 0 otherwise.  Each Tcl channel is in blocking mode unless configured
otherwise.
.\" METHOD: close

.TP
\fBchan close \fIchannelName\fR ?\fIdirection\fR?
.
Closes and destroys the named channel, deleting any existing event handlers
established for the channel, and returns the empty string.  If \fIdirection\fR is
given, it is
.QW\fBread\fR
or
.QW\fBwrite\fR
or any unique abbreviation of those words, and only that side of the channel is
closed. I.e. a read-write channel may become read-only or write-only.





Closing a read-only channel for reading, or closing a write-only channel for


writing is the same as simply closing the channel.  It is an error to close a
read-only channel for writing or to close a write-only channel for reading.
.RS
.PP
When a channel is closed for writing, any buffered output on the channel is
flushed. When a channel is closed for reading, any buffered input is discarded.
When a channel is destroyed the underlying resource is closed and the channel
is thereafter unavailable.

.PP


\fBchan close\fR fully flushes any output before closing the write side of a
channel unless it is non-blocking mode, where it returns immediately and the
channel is flushed in the background before finally being closed.

.PP
\fBchan close\fR may return an error if an error occurs while flushing
output.  If a process in a command pipeline created by \fBopen\fR returns an
error (either by returning a non-zero exit code or writing to its standard
error file descriptor), \fBchan close\fR generates an error in the same
manner as \fBexec\fR.
.PP



Closing one side of a socket or command pipeline may lead to the shutdown() or

close() of the underlying system resource, leading to a reaction from whatever
is on the other side of the pipeline or socket.


.PP

If the channel for a command pipeline is in blocking mode, \fBchan close\fR
waits for the connected processes to complete.
.PP


\fBchan close\fR only affects the current interpreter.  If the channel is open
in any other interpreter, its state is unchanged there.  See \fBinterp\fR for a
description of channel sharing.
.PP

When the last interpreter sharing a channel is destroyed, the channel is
switched to blocking mode and fully flushed and then closed.
.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 \fIchannelName\fR ?\fIoptionName\fR? ?\fIvalue\fR? ?\fIoptionName value\fR?...






















.
Configures or reports the configuration of \fIchannelName\fR.
.RS
.PP
If no \fIoptionName\fR or \fIvalue\fR arguments are given,
\fBchan configure\fR returns a dictionary of option names and
values for the channel.  If \fIoptionName\fR is supplied without a \fIvalue\fR,
\fBchan configure\fR returns the current value of the named option.  If one or
more pairs of \fIoptionName\fR and \fIvalue\fR are supplied,

\fBchan configure\fR sets each of the named options to the corresponding
\fIvalue\fR and returns the empty string.
.PP
The options described below are supported for all channels. Each type of
channel may provide additional options. Those options are described in the
relevant documentation. For example, additional options are documented for
\fBsocket\fR, and also for serial devices at \fBopen\fR.
.\" OPTION: -blocking



.TP
\fB\-blocking\fI boolean\fR
.
If \fB\-blocking\fR is set to \fBtrue\fR, which is the default, reading from or
writing to the channel may cause the process to block indefinitely.  Otherwise,
operations such as \fBchan gets\fR, \fBchan read\fR, \fBchan puts\fR, \fBchan
flush\fR, and \fBchan close\fR take care not to block.  Non-blocking mode in
generally requires that the event loop is entered, e.g. by calling
\fBTcl_DoOneEvent\fR or \fBvwait\fR or by using Tk, to give Tcl a chance to
process events on the channel.


.\" OPTION: -buffering




.TP
\fB\-buffering\fI newValue\fR
.
If \fInewValue\fR is \fBfull\fR, which is the default, output is buffered
until the internal buffer is full or until \fBchan flush\fR is called. If
\fInewValue\fR is \fBline\fR, output is flushed each time a end-of-line
character is written. If \fInewValue\fR is \fBnone\fR, output is flushed after
every output operation.  For \fBstdin\fR, \fBstdout\fR, and channels that
connect to terminal-like devices, the default value is \fBline\fR.  For
\fBstderr\fR the default value is \fBnone\fR.
.\" OPTION: -buffersize
.TP
\fB\-buffersize\fI newSize\fR
.
\fInewSize\fR, an integer no greater than one million, is the size in bytes of
any input or output buffers subsequently allocated for this channel.
.\" OPTION: -encoding
.TP
\fB\-encoding\fR ?\fIname\fR?
.
Sets the encoding of the channel.  \fIname\fR is either one of the names
returned by \fBencoding names\fR, or
.QW \fBbinary\fR


\&. Input is converted from the encoding into Unicode, and output is converted

from Unicode to the encoding.


.RS
.PP



\fBbinary\fR is an alias for \fBiso8859-1\fR.  This alone is not sufficient for

working with binary data.  Use \fB\-translation binary\fR instead.


.PP
The encoding of a new channel is the value of \fBencoding system\fR,
which returns the platform- and locale-dependent system encoding used to
interface with the operating system,
.RE

.\" OPTION: -eofchar
.TP
\fB\-eofchar\fI char\fR
.


\fIchar\fR signals the end of the data when it is encountered in the input.

If \fIchar\fR is the empty string, there is no special character that marks

the end of the data.







.RS
.PP
The default value is the empty string.  The acceptable range is \ex01 -
\ex7F.  A value outside this range results in an error.
.RE
.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\fI translation\fR
.TP
\fB\-translation\fR \fB{\fIinTranslation outTranslation\fB}\fR
.
In Tcl a single line feed (\en) represents the end of a line.  However,

at the destination 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 line feed is used in files and a
carriage-return-linefeed sequence is normally used in network connections.
Therefore, on input, e.g. with \fBchan gets\fR and \fBchan read\fR, each
external end-of-line character is translated into a line feed.  On
output, e.g. with \fBchan puts\fR, each line feed is translated to the external

end-of-line character.  The default translation, \fBauto\fR, handles all the
common cases, and \fB\-translation\fR provides explicit control over the
end-of-line character.
.RS
.PP
Returns the input translation for a read-only channel, the output translation
for a write-only channel, and both the input translation and the the output
translation for a  read-write channel.  When two translations are given, they
are the input and output translation, respectively.  When only one translation
is given for a read-write channel, it is the translation for both input and



output.  The following values are currently supported:

.IP \fBauto\fR


The default.  For input each occurrence of a line feed (\fBlf\fR), carriage
return (\fBcr\fR), or carriage return followed by a line feed (\fBcrlf\fR) is


translated into a line feed.  For output, each line feed is translated into a
platform-specific representation:  For all Unix variants it is \fBlf\fR, and
for all Windows variants it is \fBcrlf\fR, except that for sockets on all


platforms it is \fBcrlf\fR for both input and output.

.IP \fBbinary\fR

Like \fBlf\fR, no end-of-line translation is performed, but in addition, sets

\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 is represented in the external data by a single carriage
return character.  For input, each carriage return is translated to a line

feed, and for output each line feed character is translated to a carriage
return.

.IP \fBcrlf\fR

The end of a line is represented in the external data by a carriage return
character followed by a line feed.  For input, each carriage-return-linefeed
sequence is translated to a line feed.  For output, each line feed is
translated to a carriage-return-linefeed sequence.  This translation is


typically used for network connections, and also on Windows systems.

.IP \fBlf\fR

The end of a line in the external data is represented by a line feed so no

translations occur during either input or output.  This translation is
typically used on UNIX platforms,
.RE
.RE
.\" METHOD: copy
.TP
\fBchan copy \fIinputChan outputChan\fR ?\fB\-size \fIsize\fR? ?\fB\-command \fIcallback\fR?
.
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

copies and to avoid buffering too much data in main memory when copying large
files to slow destinations like network sockets.
.RS
.PP



\fB\-size\fR limits the number of characters copied.





.PP

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

additional argument the number of characters written to \fIoutputChan\fR.  If
an error occurs during the background copy, another argument provides message

for the error.  \fIinputChan\fR and \fIoutputChan\fR are automatically
configured for non-blocking mode if needed.  Background copying only works

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
\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, copying ceases and \fBno\fR callback is made.  If \fIinputChan\fR is
closed all data already queued is written to \fIoutputChan\fR.
.PP
There should be no event handler established for \fIinputChan\fR  because it

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.























.RE
.\" METHOD: create
.TP
\fBchan create \fImode cmdPrefix\fR
.
Creates a new channel, called a \fBreflected\fR channel, with \fIcmdPrefix\fR

as its handler, and returns the name of the channel.  \fBcmdPrefix\fR is the

first words of a command that provides the interface for a \fBrefchan\fR.



.RS
.PP


\fBImode\fR is a list of one or more of the strings
.QW \fBread\fR
or
.QW \fBwrite\fR ,
indicating whether the channel is a read channel, a write channel, or both.

It is an error if the handler does not support the chosen mode.

.PP
The handler is called as needed from the global namespace at the top level, and

command resolution happens there at the time of the call.  If the handler is



renamed or deleted any subsequent attempt to call it is an error, which may
not be able to describe the failure.

.PP

The handler is always called in the interpreter and thread it was created in,
even if the channel was shared with or moved into a different interpreter in a


different thread.  This is achieved through event dispatch, so if the event




loop is not entered, e.g. by calling \fBTcl_DoOneEvent\fR or \fBvwait\fR or
using Tk, the thread performing the channel operation \fIblocks
indefinitely\fR, resulting in deadlock.
.PP
One side of a channel may be in one thread while the other side is in a
different thread, providing a stream-oriented bridge between the threads. This

provides a method for regular stream communication between threads as an
alternative to sending commands.
.PP
When the interpreter the handler is in is deleted each channel associated with

the handler is deleted as well, regardless of which interpreter or thread it


is currently in or shared with.
.PP
\fBchan create\fR is \fBsafe\fR and is accessible to safe interpreters.  The
handler is always called in the safe interpreter it was created in.
.RE
.\" METHOD: eof
.TP










\fBchan eof \fIchannelName\fR
.

Returns 1 if the last read on the channel failed because the end of the data
was already reached, and 0 otherwise.
.\" METHOD: event
.TP
\fBchan event \fIchannelName event\fR ?\fIscript\fR?
.
Arranges for the given script, called a \fBchannel event handler\fR, to be
called whenever the given event, one of

.QW \fBreadable\fR

or
.QW \fBwritable\fR
occurs on the given channel, replacing any script that was previously set.  If
\fIscript\fR is the empty string the current handler is deleted.  It is also
deleted when the channel is closed.  If \fIscript\fR is omitted, either the
existing script or the empty string is returned.  The event loop must be

entered, e.g. via \fBvwait\fR or \fBupdate\fR, or by using Tk, for handlers to
be evaluated.
.RS
.PP

\fIscript\fR is evaluated at the global level in the interpreter it was
established in.  Any resulting error is handled in the background, i.e. via
\fBinterp bgerror\fR.  In order to prevent an endless loop due to a buggy
handler, the handler is deleted if \fIscript\fR returns an error so that it is
not evaluated again.




.PP
Without an event handler, \fBchan gets\fR or \fBchan read\fR on a channel in
blocking mode may block until data becomes available, become during which the
thread is unable to perform other work or respond to events on other channels.
This could cause the application to appear to
.QW "freeze up"
\&.
Channel event handlers allow events on the channel to direct channel handling
so that the reader or writer can continue to perform other processing while
waiting for a channel to become available and then handle channel operations
when the channel is ready for the operation.
.PP
A
.QW readable


event occurs when there is data that can be read from the channel and also when

there is an error on the channel.  The handler must check for these conditions



and handle them appropriately.  For example, a handler that does not check
whether the end of the data has been reached may be repeatedly evaluated in a
busy loop until the channel is closed.


.PP
A
.QW writable
event occurs when at least one byte of data can be written, or if there is an

error on the channel.  A client socket opened in non-blocking mode becomes
writable when it becomes connected or if the connection fails.
.PP
Event-driven channel handling works best for channels in non-blocking mode.  A

channel in blocking mode blocks when \fBchan puts\fR writes more data than the
channel can accept at the moment, and when \fBchan gets\fR or \fBchan read\fR
requests more data than is currently available.  When a channel blocks, the
thread can not do any other processing or service any other events.  A channel
in non-blocking mode allows a thread to carry on with other work and get back





to the channel at the right time.



.RE
.\" METHOD: flush
.TP
\fBchan flush \fIchannelName\fR
.




For a channel in blocking mode, flushes all buffered output to the destination,

and then returns.  For a channel in non-blocking mode, returns immediately
while all buffered output is flushed in the background as soon as possible.

.\" METHOD: gets

.TP
\fBchan gets \fIchannelName\fR ?\fIvarName\fR?
.
Returns the next line from the channel, removing the trailing line feed, or if
\fIvarName\fR is given, assigns the line to that variable and returns the
number of characters read.
the line that was read, removing the trailing line feed, or returns the
empty string if there is no data to return and the end of the file has been
reached, or in non-blocking mode, if no complete line is currently available.
If \fIvarName\fR is given, assigns the line that was read to variable named

\fIvarName\fR  and returns the number of characters that were read, or -1 if
there no data available and the end of the channel was reached or the channel
is in non-blocking mode.

.RS
.PP

If the end of the channel is reached the data read so far is returned or
assigned to \fIvarName\fR. When \fIvarName\fR is not given, \fBchan eof\fR may
indicate that the empty string means that the end of the data has been reached,

and \fBchan blocked\fR may indicate that that the empty string means there
isn't currently enough data do return the next line.
.RE
.\" METHOD: names
.TP
\fBchan names\fR ?\fIpattern\fR?
.
Returns a list of all channel names, or if \fIpattern\fR is given, only those
names that match according to the rules of \fBstring match\fR.
.\" METHOD: pending
.TP
\fBchan pending \fImode channelName\fR
.

Returns the number of bytes of input
when \fImode\fR is
.QW\fBinput\fR
, or output when \fImode\fR is
.QW\fBoutput\fR
, that are currently internally buffered for the channel.  Useful in a readable
event callback to impose limits on input line length to avoid a potential
denial-of-service attack where an extremely long line 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 pipe, i.e. a readable channel and a writable channel, and returns the

names of the readable channel and the writable channel.  Data written to the
writable channel can be read from the readable channel.  Because the pipe is a
real system-level pipe, it can be connected to other processes using
redirection.  For example, to redirect \fBstderr\fR from a subprocess into one
channel, and \fBstdout\fR into another, \fBexec\fR with "2>@" and ">@", each
onto the writable side of a pipe, closing the writable side immediately

thereafter so that EOF is signaled on the read side once the subprocess has
closed its output, typically on exit.
.RS
.PP
Due to buffering, data written to one side of a pipe might not immediately


become available on the other side.  Tcl's own buffers can be configured via
\fBchan configure -buffering\fR, but overall behaviour still depends on
operating system buffers outside of Tcl's control. Once the write side of the
channel is closed, any data remaining in the buffers is flushed through to the
read side.  It may be useful to arrange for the connected process to flush at
some point after writing to the channel or to have it use some system-provided
mechanism to configure buffering.  When two pipes are connected to the same

process, one to send data to the process, and one to read data from the
process, a deadlock may occur if the channels are in blocking mode:  If
reading, the channel may block waiting for data that can never come because
buffers are only flushed on subsequent writes, and if writing, the channel may
block while waiting for the buffers to become free, which can never happen
because the reader can not read while the writer is blocking.  To avoid this
issue, either put the channels into non-blocking mode and use event handlers,
or place the read channel and the write channel in separate interpreters in
separate threads.
.RE
.\" METHOD: pop
.TP
\fBchan pop \fIchannelName\fR
.
Removes the topmost transformation handler from the channel if there is one,

and closes the channel otherwise. The result is normally the empty string, but
may be an error in some situations, e.g. when closing the underlying resource
results in an error.
.\" METHOD: postevent
.TP
\fBchan postevent \fIchannelName eventSpec\fR
.










For use by handlers established with \fBchan create\fR.  Notifies Tcl that
that one or more event(s) listed in \fIeventSpec\fR, each of which is either
.QW\fBread\fR
or
.QW\fBwrite\fR.
, have occurred.
.RS
.PP
For use only by handlers for a channel created by \fBchan create\fR.  It is an

error to post an event for any other channel.
.PP
Since only the handler for a reflected channel channel should post events it is
an error to post an event from any interpreter other than the interpreter that

created the channel.
.PP


It is an error to post an event that the channel has no interest in.  See
\fBwatch\fR in the \fBrefchan\fR documentation for more information

.PP

\fBchan postevent\fR is available in safe interpreters, as any handler for a

reflected channel would have been created, and will be evaluated in that

interpreter as well.
.RE
.\" METHOD: push
.TP
\fBchan push \fIchannelName cmdPrefix\fR
.
Adds a new transformation handler on top of the channel and returns a handle

for the transformation.  \fIcmdPrefix\fR is the first words of a command that
provides the interface documented for \fBtranschan\fR, and transforms data on
the channel, It is an error if handler does not support the mode(s) the channel
is in.
.\" METHOD: puts

.TP
\fBchan puts\fR ?\fB\-nonewline\fR? ?\fIchannelName\fR? \fIstring\fR
.
Writes \fIstring\fR and a line feed to the channel.  If \fB\-nonewline\fR is
given, the trailing line feed is not written. The default channel is


\fBstdout\fR.
.RS
.PP
Each line feed in the output is translated according to the configuration of

\fB\-translation\fR.



.PP
Because Tcl internally buffers output, characters written to a channel may not
immediately be available at the destination.  Tcl normally delays output until
the buffer is full or the channel is closed. \fBchan flush\fR forces output in


the direction of the destination.
.PP
When the output for a channel in blocking mode fills up, \fBchan puts\fR blocks
until space in the buffer is available again, but for a channel in non-blocking



mode, it returns immediately and the data is written in the background as fast



possible, constrained by the speed at which as the destination accepts it.
Output to a channel in non-blocking mode only works properly when the
application enters the event loop, giving Tcl a chance to find out that the
destination is ready to accept more data.  When a channel is in non-blocking
mode, Tcl's internal buffers can hold an arbitrary amount of data, possibly
consuming a large amount of memory.  To avoid wasting memory, channels in
non-blocking mode should normally be handled using \fBchan event\fR, where the
application only invokes \fBchan puts\fR after being recently notified through
a file event handler that the channel is ready for more output data.
.RE
.\" METHOD: read
.TP
\fBchan read \fIchannelName\fR ?\fInumChars\fR?
.TP
\fBchan read \fR?\fB\-nonewline\fR? \fIchannelName\fR
.
Reads and returns the next \fInumChars\fR characters from the channel. If

\fInumChars\fR is omitted, all available characters up to the end of the file
are read, or if the channel is in non-blocking mode, all currently-available
characters are read.  If there is an error on the channel, reading ceases and
an error is returned.  If \fInumChars\fR is not given, \fB\-nonewline\fR
may be given, causing any any trailing line feed to be trimmed.

.RS
.PP
If the channel is in non-blocking mode, fewer characters than requested may be


returned.  If the channel is configured to use a multi-byte encoding, bytes

that do not form a complete character are retained in the buffers until enough
bytes to complete the character accumulate, or the end of the data is reached.
\fB\-nonewline\fR is ignored if characters are returned before reaching the end
of the file.
.PP
Each end-of-line sequence according to the value of \fB\-translation\fR is
translated into a line feed.


.PP















When reading from a serial port, most applications should configure the serial

port channel to be in non-blocking mode, but not necessarily use an event

handler since most serial ports are comparatively slow.  It is entirely
possible to get a \fBreadable\fR event for each individual character.  In
blocking mode, \fBchan read\fR blocks forever when reading to the end of the
data if there is no \fBchan configure -eofchar\fR configured for the channel.


.RE
.\" METHOD: seek
.TP
\fBchan seek \fIchannelName offset\fR ?\fIorigin\fR?
.
Sets the current position for the data in the channel to integer \fIoffset\fR
bytes relative to \fIorigin\fR.  A negative offset moves the current position
backwards from the origin.  \fIorigin\fR is one of the
following:
.RS

.IP \fBstart\fR

The origin is the start of the data.  This is the default.


.IP \fBcurrent\fR

The origin is the current position.



.IP \fBend\fR




The origin is the end of the data.
.PP


\fBChan seek\fR flushes all buffered output even if the channel is in

non-blocking mode, discards any buffered and unread input, and returns the

empty string or an error if the channel does not support seeking.
.PP
\fIoffset\fR values are byte offsets, not character offsets.  Unlike \fBchan
read\fR, both \fBchan seek\fR and \fBchan tell\fR operate in terms of bytes,
not characters,
.RE
.\" METHOD: tell
.TP
\fBchan tell \fIchannelName\fR
.

Returns the offset in bytes of the current position in the underlying data, or
-1 if the channel does not support seeking. The value can be passed to \fBchan
seek\fR to set current position to that offset.


.\" METHOD: truncate
.TP
\fBchan truncate \fIchannelName\fR ?\fIlength\fR?
.
Flushes the channel and truncates the data in the channel to \fIlength\fR
bytes, or to the current position in bytes if \fIlength\fR is omitted.


.
.SH EXAMPLES
.SS "SIMPLE CHANNEL OPERATION EXAMPLES"
.PP
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
805
806
807
808

    \fI# Save offset of start of next line for later\fR
    set offset [\fBchan tell\fR $f]
}
\fBchan close\fR $f
.CE
.PP
A network server that does echoing of 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
}

# This is called whenever a new client connects to the server
proc connect {chan host port} {
    set clientName [format <%s:%d> $host $port]
    log "connection from $clientName"







|
|



|







631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650

    \fI# Save offset of start of next line for later\fR
    set offset [\fBchan tell\fR $f]
}
\fBchan close\fR $f
.CE
.PP
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
}

# This is called whenever a new client connects to the server
proc connect {chan host port} {
    set clientName [format <%s:%d> $host $port]
    log "connection from $clientName"
824
825
826
827
828
829
830
831




















































































832
833
834
835
836
837
838
839
840
    }
}

# Create the server socket and enter the event-loop to wait
# for incoming connections...
socket -server connect 12345
vwait forever
.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)
.SH KEYWORDS
channel, input, output, events, offset
'\" Local Variables:
'\" mode: nroff
'\" End:








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









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

# Create the server socket and enter the event-loop to wait
# for incoming connections...
socket -server connect 12345
vwait forever
.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)
.SH KEYWORDS
channel, input, output, events, offset
'\" 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
.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

\fBoo::class\fI method \fR?\fIarg ...\fR?
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
   \(-> \fBoo::class\fR







|







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

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

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

.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







>










>

















>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
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

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

\fBclassvariable\fR \fIvariableName\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
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







|

|










|
|







9
10
11
12
13
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 tcl::oo

\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 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
'\"
'\" Generated from file './doc/clock.dt' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2004 Kevin B. Kenny <[email protected]>. 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"

package require \fBTcl 8.5\fR
.sp
\fBclock add\fR \fItimeVal\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...?
.sp
\fBclock microseconds\fR
.sp
\fBclock milliseconds\fR
.sp
\fBclock scan\fR \fIinputString\fR ?\fI\-option value\fR...?
.sp
\fBclock seconds\fR
.sp
.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.

.TP
\fBclock add\fR \fItimeVal\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.

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

.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

.TP
\fBclock format\fR \fItimeVal\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.

.TP
\fBclock microseconds\fR

Returns the current time as an integer number of microseconds.  See \fBHIGH RESOLUTION TIMERS\fR for a full description.


.TP
\fBclock milliseconds\fR

Returns the current time as an integer number of milliseconds.  See \fBHIGH RESOLUTION TIMERS\fR for a full description.


.TP
\fBclock scan\fR \fIinputString\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.

.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









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

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

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

.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"
or any of the equivalent ways to specify it.

.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

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










>
|
|
|
<

<
|
<

<

<
|
<

|






>

|
>


>


>



|
>












>

|
>



>


>
|
>
>


>
|
>
>

|
>



>


>




>




>









>
>
>
>
>
>
>
>
>

>





>


>



>


>



















>


>





|

>


>













>


>







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

15

16

17

18

19

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
'\"
'\" Generated from file './doc/clock.dt' by tcllib/doctools with format 'nroff'
'\" Copyright (c) 2004 Kevin B. Kenny <[email protected]>. 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

\fBclock add\fI timeVal\fR ?\fIcount unit...\fR? ?\fI\-option value\fR?

\fBclock clicks\fR ?\fI\-option\fR?

\fBclock format\fI timeVal\fR ?\fI\-option value\fR...?

\fBclock microseconds\fR

\fBclock milliseconds\fR

\fBclock scan\fI inputString\fR ?\fI\-option value\fR...?

\fBclock seconds\fR
.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\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.
.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\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.
.\" 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.
.\" METHOD: scan
.TP
\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
\fI\-now\fR
Instead of \fItimeVal\fR a non-integer option \fI\-now\fR can be used as
replacement for today, which is simply interpolated to the runt-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
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\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:
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
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
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
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.







|

|







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
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
the fact that Tcl's model of time reacts to leap seconds by speeding
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
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" ,
the obsolete usage
.QW "\fB\-gmt\fR \fItrue\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.
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.
.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
\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.
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.
.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:







|

|








|





|
|

















|
|







|





|
|







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
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\fI :UTC\fR" ,
the obsolete usage
.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 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 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\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 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 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
.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.



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







|
>
|
>
>
>







418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
.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, \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.
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
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
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
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
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)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
This format group is synonymous with \fB%b\fR.
.TP
\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
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
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
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
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
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
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
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
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
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
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
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
This format group is reserved for internal use within the Tcl library.
.TP

\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
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
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
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
On output, produces a TAB character. On input, matches a TAB character.
.TP
\fB%T\fR
Synonymous with \fB%H:%M:%S\fR.
.TP
\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
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
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
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
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
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
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
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
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
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.
.TP

\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. 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
On output, produces a literal
.QW \fB%\fR
character. On input, matches a literal
.QW \fB%\fR
character.
.TP
\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).
.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]







<
|
|



<
|
|



<
|
|



<
|
|



<
|



<
|



<
|



<
|



<
|




<
|




<
|



<
|







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




<
|



<
|



<
|



<
|




<
|




<
|

<
|


<
|


<
|


<
|
|





<
|


<
|


<
|



<
|



<
|




<
|





<
|





<
|





<
|

<
>
|


<
|



<
|





<
|



<
|

<
|

<
|




<
|






<
|






<
|





<
|





<
|



<
|



<
|





<
|




<
|



|
<
>
|



>
|




<
|





<
|












|







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

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

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

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

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

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

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

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

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

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

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

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

.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.
.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 fraktion (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 fraktion (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.

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

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

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

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

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

.IP \fB%h\fR
This format group is synonymous with \fB%b\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.

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

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

.IP \fB%J\fR
On output, produces a string of digits giving the calendar 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.

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

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

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

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

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

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

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

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

.IP \fB%Q\fR
This format group is reserved for internal use within the Tcl library.

.\" 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.

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

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

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

.IP \fB%t\fR
On output, produces a TAB character. On input, matches a TAB character.

.IP \fB%T\fR
Synonymous with \fB%H:%M:%S\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.

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

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

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

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

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

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

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

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

.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 (this token is optionally applicable on input,

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

.IP \fB%%\fR
On output, produces a literal
.QW \fB%\fR
character. On input, matches a literal
.QW \fB%\fR
character.

.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 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]
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
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.
.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







|







836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
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
\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
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
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

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







|




|
|
>







860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
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 \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.
\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
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
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",
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".
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
giving an explicit \fB\-format\fR option to the \fBclock scan\fR command.
.TP
\fIrelative time\fR
.







|








|





|







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
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" ,
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: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
giving an explicit \fB\-format\fR option to the \fBclock scan\fR command.
.TP
\fIrelative time\fR
.
942
943
944
945
946
947
948


















949
950
951
952
953
954
955
956
957
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.


















.SH "SEE ALSO"
msgcat(n)
.SH KEYWORDS
clock, date, time
.SH "COPYRIGHT"
Copyright (c) 2004 Kevin B. Kenny <[email protected]>. All rights reserved.
'\" Local Variables:
'\" mode: nroff
'\" End:







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





|



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
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 \(co 2004 Kevin B. Kenny <[email protected]>. 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
.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)?
.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







|



|
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.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 ?\fBr\fR(\fBead\fR)|\fBw\fR(\fBrite\fR)?
.BE
.SH DESCRIPTION
.PP
Closes or half-closes the channel given by \fIchannelId\fR. \fBchan close\fR
is another name for this command.
.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
45
46
47
48
49
50
51
52







53
54
55
56

57
58
59
60
61
62
63
64
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







|
>
>
>
>
>
>
>



|
>
|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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
\fBTCL_FLUSH_NONBLOCKING_ON_EXIT\fR, which when set and not equal to
.QW \fB0\fR
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 (either by returning a
non-zero exit code or writing to its standard error file descriptor),
\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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
        uplevel 1 $script
    } result options
    \fBclose\fR $chan
    return -options $options $result
}
.CE
.SH "SEE ALSO"
file(n), open(n), socket(n), eof(n), Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, channel, close, nonblocking, half-close
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:







|






100
101
102
103
104
105
106
107
108
109
110
111
112
113
        uplevel 1 $script
    } result options
    \fBclose\fR $chan
    return -options $options $result
}
.CE
.SH "SEE ALSO"
chan(n), file(n), open(n), socket(n), eof(n), Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, channel, close, nonblocking, half-close
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/concat.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
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}}
\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"
\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 }
\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).








.SH "SEE ALSO"
append(n), eval(n), join(n)
.SH KEYWORDS
concatenate, join, list
'\" Local Variables:
'\" mode: nroff
'\" End:







|







|







|





>
>
>
>
>
>
>
>

|





24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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% \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% \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% \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), 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 © 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
.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 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 \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:

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

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

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

.TP
\fB\-domainrefresh \fIintervalMilliseconds\fR
.
The number of milliseconds between checks of the \fI\-domainlist\fR for new
domains.

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

.TP
\fB\-offline \fIflag\fR
.
Allows the cookie managment 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.

.TP
\fB\-purgeold \fIintervalMilliseconds\fR
.
The number of milliseconds between checks of the database for expired
cookies; expired cookies are deleted.

.TP
\fB\-retain \fIcookieCount\fR
.
The maximum number of cookies to retain in the database.

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

.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
memory, which effectively forces all cookies within it to be session cookies.
.SS "INSTANCE METHODS"
.PP
The following methods are supported on the instances:

.TP
\fIcookiejar\fR \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.

.TP
\fIcookiejar\fR \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.

.TP
\fIcookiejar\fR \fBgetCookies\fR \fIprotocol host path\fR
.
This method obtains the cookies for a particular HTTP request. \fIThis
implements the http cookie jar protocol.\fR

.TP
\fIcookiejar\fR \fBpolicyAllow\fR \fIoperation 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
.
The \fIdomain\fR is seeking to delete a cookie.
.TP
\fBsession\fR
.
The \fIdomain\fR is seeking to create or update a session cookie.
.TP
\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

.TP
\fIcookiejar\fR \fBstoreCookie\fR \fIoptions\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

.TP
\fIcookiejar\fR \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
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/]
.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
http::configure -cookiejar [MyCookieJar new $cookiedb]

# No further explicit steps are required to use cookies
set tok [http::geturl http://core.tcl.tk/]
.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:







|




|
|











>











>









>








>



|

>






>



|



>





>




>









>





|
|




>

|





>

|





>

|



>

|








<
|
<

<
|
<

<
|
<






>

|




>

|
















|



|


















|



|









11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

154

155

156

157

158

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
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\fI name\fR ?\fIfilename\fR?
\fB::http::cookiejar new\fR ?\fIfilename\fR?

\fIcookiejar\fR \fBdestroy\fR
\fIcookiejar\fR \fBforceLoadDomainData\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 \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 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
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 \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 \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 \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 \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

.IP \fBdelete\fR

The \fIdomain\fR is seeking to delete a cookie.

.IP \fBsession\fR

The \fIdomain\fR is seeking to create or update a session cookie.

.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 \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 \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 [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-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 [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-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
.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

\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







|







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 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
.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?
\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







>

|

|







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\fI command\fR ?\fIarg...\fR?
\fIname\fR ?\fIvalue...\fR?

.VS "8.7, TIP383"
\fBcoroinject \fIcoroName command\fR ?\fIarg...\fR?
\fBcoroprobe \fIcoroName command\fR ?\fIarg...\fR?
.VE "8.7, TIP383"
.fi
.BE
.SH DESCRIPTION
115
116
117
118
119
120
121
122



123
124
125
126
127
128
129
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



.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







|
>
>
>







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 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
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
    }
}
\fBcoroutine\fR j1 juggler Larry [
    \fBcoroutine\fR j2 juggler Curly [
        \fBcoroutine\fR j3 juggler Moe j1]] "Nyuck!Nyuck!Nyuck!"
.CE
.PP







|







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

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
.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
\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?

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

.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







|

|

<

<

<

<

<

>

<
















>







8
9
10
11
12
13
14
15
16
17
18

19

20

21

22

23
24
25

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
.nf
\fBpackage require dde 1.4\fR

\fBdde servername\fR ?\fB\-force\fR? ?\fB\-handler \fIproc\fR? ?\fB\-\|\-\fR? ?\fItopic\fR?

\fBdde execute\fR ?\fB\-async\fR? ?\fB\-binary\fR? \fIservice topic data\fR

\fBdde poke\fR ?\fB\-binary\fR? \fIservice topic item data\fR

\fBdde request\fR ?\fB\-binary\fR? \fIservice topic item\fR

\fBdde services \fIservice topic\fR

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

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


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.


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


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.


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

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

.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







>












>
>





>
>










>
>





>
>











>












>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
.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/
.CE
.SH "SEE ALSO"
tk(n), winfo(n), send(n)
.SH KEYWORDS
application, dde, name, remote execution
'\"Local Variables:
'\"mode: nroff
'\"End:







|








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

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.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
.SH SYNOPSIS
.nf
package require TclOO

\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?
.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







|







<







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

23
24
25
26
27
28
29
.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
.SH SYNOPSIS
.nf
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?
.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
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:

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







>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
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

.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

.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

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

.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

.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

.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







>
















>
















>








>



















>









>







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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
.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

.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

.TP
\fBself\fI subcommand arg ...\fR
.TP
\fBself\fI script\fR
.TP
\fBself\fR
.







>



















>







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
.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
.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

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

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

.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







>











>









>







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
.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
extremely unlikely.
.VE TIP500
.RE
.SS "ADVANCED CLASS CONFIGURATION OPTIONS"
.PP
The following definitions are also supported, but are not required in simple
programs:

.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







>







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
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
.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

.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.

.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.

.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.

.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:

.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.

.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

.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







>








>










>








>
















>







>
















>







286
287
288
289
290
291
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
.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
.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

.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.

.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

.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.

.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







>








>

















>








>







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
.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
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:

.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.

.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.

.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.

.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.

.TP
\fBself \fR
.VS TIP470
This gives the name of the object currently being configured.
.VE TIP470
.SH "PRIVATE METHODS"
.VS TIP500







>






>








>











>










>







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
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
\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. The class defines five operations (as methods) that may be done on
the slot:

.TP
\fIslot\fR \fB\-append\fR ?\fImember ...\fR?
.
This appends the given \fImember\fR elements to the slot definition.








.TP
\fIslot\fR \fB\-clear\fR
.
This sets the slot definition to the empty list.

.TP
\fIslot\fR \fB\-prepend\fR ?\fImember ...\fR?
.VS TIP516
This prepends the given \fImember\fR elements to the slot definition.
.VE TIP516

.TP
\fIslot\fR \fB\-remove\fR ?\fImember ...\fR?
.VS TIP516
This removes the given \fImember\fR elements from the slot definition.
.VE TIP516

.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.
.SS "SLOT IMPLEMENTATION"

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:

.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

.TP
\fIslot\fR \fBResolve\fR \fIslotElement\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

.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







|

>




>
>
>
>
>
>
>
>




>





>





>









>






>















>

|
















>







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
\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. The 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.
.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\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: 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

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
.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:

.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

.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.)

.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.

.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
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

.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.

.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







>













>






>







>









>







|










>



>















>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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 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
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


.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"

.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

.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.

.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.

.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

.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,







>
>
















>















>








>







>















>







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
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
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

.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.

.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.

.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.

.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

.TP
\fBdict size \fIdictionaryValue\fR
.
Return the number of key/value mappings in the given dictionary value.

.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

.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,







>








>








>








>













>




>
















>







212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
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
.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).

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

.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.

.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







>




>








>







303
304
305
306
307
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
.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).

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







>







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
'\"
'\" Copyright (c) 1998 by 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.


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
.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:

.TP
\fBencoding convertfrom\fR ?\fIencoding\fR? \fIdata\fR


.
Convert \fIdata\fR to Unicode from the specified \fIencoding\fR.  The
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
system encoding is used.










.TP
\fBencoding convertto\fR ?\fIencoding\fR? \fIstring\fR


.
Convert \fIstring\fR from Unicode to the specified \fIencoding\fR.
The result is a sequence of bytes that represents the converted
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.





.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.

.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.

.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.














































.SH EXAMPLE









.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
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"]

.CE
.PP
would return the Unicode string
.QW "\eu306F" ,
which is the Hiragana letter HA.







































.SH "SEE ALSO"
Tcl_GetEncoding(3)
.SH KEYWORDS
encoding, unicode
.\" Local Variables:
.\" mode: nroff
.\" End:

|
>








|

|



>
>
>
|
>
>
|
|
|
|
<
|
>
|
|
|

>
>
|
>
|
<
>
|
>
>
>
>
>


|
<
>


>
>

|
<
<
<
<
|
>
>
>
>
>
>
>
>
>
>

|
>
>

<
<
<
<
|
|
>
>
>
>
>



<
<
|
|
|
|
<
<
|
>



|
<





>

>
>
>
>
>
>
>


|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|


|
>


|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55




56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71




72
73
74
75
76
77
78
79
80
81


82
83
84
85


86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
















168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
'\"
'\" Copyright (c) 1998 Scriptics Corporation.
'\" Copyright (c) 2023 Nathan Coulter
'\"
'\" 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 \- Work with encodings
.SH SYNOPSIS
\fBencoding \fIoperation\fR ?\fIarg arg ...\fR?
.BE
.SH INTRODUCTION
.PP
In Tcl every string is composed of Unicode values.  Text may be encoded into an
encoding such as cp1252, iso8859-1, Shift\-JIS, utf-8, utf-16, etc. Not every
Unicode value is encodable in every encoding, and some encodings can encode
values that are not available in Unicode.
.PP
Even though Unicode is for encoding the written texts of human languages, any
sequence of bytes can be encoded as the first 255 Unicode values. In particular,
iso8859-1 is an encoding (a superset of classic ASCII) for a subset of Unicode
in which each byte is a Unicode value of 255
or less; any sequence of bytes can be considered to be a Unicode string

encoded in iso8859-1.  To work with binary data in Tcl, decode it from
iso8859-1 when reading it in, and encode it into iso8859-1 when writing it out,
ensuring that each character in the string has a value of 255 or less.
Decoding such a string does nothing, and encoding encoding such a string also
does nothing.
.PP
For example, the following is true:
.CS

set text {In Tcl binary data is treated as Unicode text and it just works.}
set encoded [\fBencoding convertto\fR iso8859-1 $text]

expr {$text eq $encoded}; #-> 1
.CE
The following is also true:
.CS
set decoded [\fBencoding convertfrom\fR iso8859-1 $text]
expr {$text eq $decoded}; #-> 1
.CE
.SH DESCRIPTION
.PP
Performs one of the following encoding \fIoperations\fR:

.\" METHOD: convertfrom
.TP
\fBencoding convertfrom\fR ?\fIencoding\fR? \fIdata\fR
.TP
\fBencoding convertfrom\fR ?\fB\-profile \fIprofile\fR? ?\fB\-failindex var\fR? \fIencoding data\fR
.
Decodes \fIdata\fR encoded in \fIencoding\fR. If \fIencoding\fR is not




specified the current system encoding is used.
.VS "TCL8.7 TIP607, TIP656"
\fB\-profile\fR determines how invalid data for the encoding are handled.  See
the \fBPROFILES\fR section below for details.  Returns an error if decoding
fails.  However, if \fB\-failindex\fR given, returns the result of the
conversion up to the point of termination, and stores in \fBvar\fR the index of
the character that could not be converted. 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? \fIdata\fR
.TP
\fBencoding convertto\fR ?\fB\-profile \fIprofile\fR? ?\fB\-failindex var\fR? \fIencoding data\fR
.




Converts \fIstring\fR to \fIencoding\fR.  If \fIencoding\fR is not given, the
current system encoding is used.
.VS "TCL8.7 TIP607, TIP656"
See \fBencoding convertfrom\fR for the meaning of \fB\-profile\fR and
\fB\-failindex\fR.
.VE "TCL8.7 TIP607, TIP656"
.\" METHOD: dirs
.TP
\fBencoding dirs\fR ?\fIdirectoryList\fR?
.


Sets the search path for \fB*.enc\fR encoding data files to the list of
directories given by \fIdirectoryList\fR.  If \fIdirectoryList\fR is not given,
returns the current list of directories that make up the search path.  It is
not an error for an item in \fIdirectoryList\fR to not refer to a readable,


searchable directory.
.\" METHOD: names
.TP
\fBencoding names\fR
.
Returns a list of the names of available encodings.

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 names of available encoding profiles. See \fBPROFILES\fR
below.
.VE "TCL8.7 TIP656"
.\" METHOD: system
.TP
\fBencoding system\fR ?\fIencoding\fR?
.
Sets the system encoding to \fIencoding\fR. If \fIencoding\fR is not given,
returns the current system encoding.  The system encoding is used to pass
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"
Each \fIprofile\fR is a distinct strategy for dealing with invalid data for an
encoding.
.PP
The following profiles are currently implemented.
.VE "TCL8.7 TIP656"
.TP
\fBstrict\fR
.VS "TCL8.7 TIP656"
The default profile.  The operation fails when invalid data for the encoding
are encountered.
.VE "TCL8.7 TIP656"
.TP
\fBtcl8\fR
.VS "TCL8.7 TIP656"
Provides for behaviour identical to that of Tcl 8.6: When
decoding, for encodings \fBother than utf-8\fR, each invalid byte is interpreted
as the Unicode value given by that one byte. For example, the byte 0x80, which
is invalid in the ASCII encoding would be mapped to the Unicode value U+0080.
For \fButf-8\fR, each invalid byte that is a valid CP1252 character is
interpreted as the Unicode value for that character, while each byte that is
not is treated as the Unicode value given by that one byte. 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.
.RS
.PP
When encoding, each character that cannot be represented in the encoding is
replaced by an encoding-dependent character, usually the question mark \fB?\fR.
.RE
.VE "TCL8.7 TIP656"
.TP
\fBreplace\fR
.VS "TCL8.7 TIP 656"
When decoding, invalid bytes are replaced by U+FFFD, the Unicode REPLACEMENT
CHARACTER.
.RS
.PP
When encoding, Unicode values 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.
.RE
.VE "TCL8.7 TIP656"
.SH EXAMPLES
.PP
These examples use the utility proc below that prints the Unicode value for
each character in a string.
.PP
.CS
proc codepoints s {join [lmap c [split $s {}] {
    string cat U+ [format %.6X [scan $c %c]]}]
}
.CE
.PP
















Example 1: Convert from euc-jp:
.PP
.CS
% codepoints [\fBencoding convertfrom\fR euc-jp \exA4\exCF]
U+00306F
.CE
.PP
The result is the Unicode value
.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 -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 -failindex idx iso8859-1 A\eu0141
A
% set idx
1
.CE
.VE "TCL8.7 TIP607, TIP656"
.PP
.SH "SEE ALSO"
Tcl_GetEncoding(3), fconfigure(n)
.SH KEYWORDS
encoding, unicode
.\" Local Variables:
.\" mode: nroff
.\" End:

Changes to doc/error.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.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







<







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
.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).

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.







.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:







>

|
>
>
>
>
>
>
>







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;
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
.PP
However, the last line would now normally be written without
\fBeval\fR, like this:
.PP
.CS
set var [linsert $var 0 {*}$args]
.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:







>
>
>
>
>
>








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
.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.




.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:

.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.

.TP 13
\fB\-keepnewline\fR
.
Retains a trailing newline in the pipeline's output.
Normally a trailing newline will be deleted.

.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" ,
\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
.







>
>
>
>





>





>





>











|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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<\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
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
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







|







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;
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
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
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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















<
<
<
<
<
<
<
<
<







232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
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









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
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.
.IP \(bu 3
The Windows NT 16-bit system directory.
.IP \(bu 3
The Windows NT 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.







|

<
<
|







319
320
321
322
323
324
325
326
327


328
329
330
331
332
333
334
335
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 32-bit system directory.
.IP \(bu 3


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.
418
419
420
421
422
423
424

425

426
427
428
429
430
431
432
.CE
.PP
With the file \fIcmp.bat\fR looking something like:
.PP
.CS
@gcc %*
.CE

or like another variant using single parameters:

.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







>

>







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
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"
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:







|










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 [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
.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







<







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
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-2000 Sun Microsystems, Inc.
'\" Copyright (c) 2005 by Kevin B. Kenny <[email protected]>. 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
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.


.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.
.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
\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
a discussion of how mathematical functions are handled.

.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 {{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
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:



|















|



















|
|
|
>
>
>
|
>
>




|

|
|
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|
>
>
|
|
|
|
>
|
>
>
>
>
>

|
<
<
<
|
>
|
>
|
>
>
|
|

>












|
|
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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 Kevin B. Kenny <[email protected]>. 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
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 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.  Each operand is interpreted as a numeric value if at all possible.
.PP
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.
.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 {{word one} < "word $a"}	\fI0\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
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
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.
.VE "8.7, TIP461"
.TP 20
\fB==\0\0!=\fR
.
Boolean equal and not equal.
.TP 20
\fBeq\0\0ne\fR







|







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 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
.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]}
.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
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
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,

.PP
.CS
\fBexpr\fR {hypot($x,$y)}
.CE
.PP
becomes
.PP







|













|
|



















|




|
>







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
.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]}
.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
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
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,
.PP
.CS
\fBexpr\fR {hypot($x,$y)}
.CE
.PP
becomes
.PP
375
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
.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.
.PP
.CS
set a 3
set b {$a + 2}
\fBexpr\fR $b*4
.CE
.PP







|
|
|

<
|
|







384
385
386
387
388
389
390
391
392
393
394

395
396
397
398
399
400
401
402
403
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
.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.
.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
.CE
.PP
Set a variable indicating whether an environment variable is defined and has
value of true:
.PP
.CS
set isTrue [\fBexpr\fR {

    [info exists ::env(SOME_ENV_VAR)] &&

    [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 <[email protected]>. All rights reserved.
.fi
'\" Local Variables:
'\" mode: nroff

'\" End:







>

>


















|



>

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
.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 Kevin B. Kenny <[email protected]>. All rights reserved.
.fi
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:

Changes to doc/fblocked.n.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.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
.BE

.SH DESCRIPTION
.PP
The \fBfblocked\fR command returns 1 if the most recent input operation
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







<







8
9
10
11
12
13
14

15
16
17
18
19
20
21
.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
.BE

.SH DESCRIPTION
.PP
The \fBfblocked\fR command returns 1 if the most recent input operation
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

Changes to doc/fconfigure.n.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.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?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBfconfigure\fR command sets and retrieves options for channels.
.PP
\fIChannelId\fR identifies the channel for which to set or query an







|
|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.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 name\fR
\fBfconfigure \fIchannelId name value \fR?\fIname value ...\fR?
.fi
.BE
.SH DESCRIPTION
.PP
The \fBfconfigure\fR command sets and retrieves options for channels.
.PP
\fIChannelId\fR identifies the channel for which to set or query an
37
38
39
40
41
42
43

44
45

46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
.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.







>

|
>











>

|











>

|





>

|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
.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.
.\" OPTION: -blocking
.TP
\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
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).
.\" OPTION: -buffering
.TP
\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 \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.
.\" OPTION: -buffersize
.TP
\fB\-buffersize\fI newSize\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.
.\" OPTION: -encoding
.TP
\fB\-encoding\fI name\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.
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124


125










126
127
128
129
130
131
132
133
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







<
|

|

|

|
<

<
<
<
<
<
<
|
<
|
|


>
>

>
>
>
>
>
>
>
>
>
>
|







101
102
103
104
105
106
107

108
109
110
111
112
113
114

115






116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
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

.\" OPTION: -eofchar
.TP
\fB\-eofchar\fI char\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.

If \fIchar\fR is the empty string, then there is no special end of file






character marker.  The default value for \fB\-eofchar\fR is the empty

string.
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\fI mode\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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
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"







<
|
<









<
|
<












<
|
<





<
|
<







<
|
<







154
155
156
157
158
159
160

161

162
163
164
165
166
167
168
169
170

171

172
173
174
175
176
177
178
179
180
181
182
183

184

185
186
187
188
189

190

191
192
193
194
195
196
197

198

199
200
201
202
203
204
205
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:

.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.

.IP \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

.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.

.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.

.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
.PP
.SH "STANDARD CHANNELS"
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
.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

# Get the header
if {[gets $f] ne "P6"} {
    error "not a raw\-bits PPM"
}

# Read lines until we have got non-comment lines







|







243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
.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

# Get the header
if {[gets $f] ne "P6"} {
    error "not a raw\-bits PPM"
}

# Read lines until we have got non-comment lines
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289

# 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)
.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:







|






|


|
|
|



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287

# 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), encoding(n), flush(n), gets(n), open(n), puts(n), read(n), socket(n),
Tcl_StandardChannels(3)
.SH KEYWORDS
blocking, buffering, carriage return, end of line, encoding, flushing, linemode,
newline, nonblocking, platform, profile, 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
.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?
.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 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
network sockets.





.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,
then the copy goes until end of file.
All the data read from \fIinchan\fR is copied to \fIoutchan\fR.


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


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







|

<


|
>


|

>
>
>
>
>

<
<
<
|
|
>
>
>
|
<
<
>
>



<
>
>







8
9
10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
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 \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 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 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



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.


.
.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.

.
.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
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

.QW "channel busy"
error.
.PP


\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
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
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.
















.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







|
>


<
>
>










|
|




|












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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
.QW "channel busy"
error.

.
.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.
.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\-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
.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?
.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
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:

.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.



.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:
.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
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).

.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. This attribute cannot be set. \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
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.



































.RE





.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.

.TP
\fBfile copy \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\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.

.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.

.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

.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.

.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.

.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.




















.TP
\fBfile isdirectory \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is a directory, \fB0\fR otherwise.

.TP
\fBfile isfile \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is a regular file, \fB0\fR otherwise.

.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

.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,







|



|
|
<
<
|
|
>









>
>
>







|
|
|
|
|


|
|
|
|
|
>
|
<
>
>
|
|
|
|
|
|
|
|
>








>
>
|
|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>







>

|




















>



















>


>













<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>







>





>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>




>




















>







8
9
10
11
12
13
14
15
16
17
18
19
20


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195















196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
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 name\fR ?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
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


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
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 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

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.
\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
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 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.















.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
.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
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

.TP
\fBfile lstat \fIname varName\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.

.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.

.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.


.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).

.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







<
<
<
|





>

|



|
|
|
|
>









>









>
>






>







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). 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\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 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
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).

.TP
\fBfile owned \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is owned by the current user, \fB0\fR
otherwise.

.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.

.TP
\fBfile readable \fIname\fR
.
Returns \fB1\fR if file \fIname\fR is readable by the current user,
\fB0\fR otherwise.

.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.

.TP
\fBfile rename \fR?\fB\-force\fR? ?\fB\-\|\-\fR? \fIsource\fR \fItarget\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.

.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.

.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.

.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.

.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.
.RE
.TP
\fBfile stat \fIname varName\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.
.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







>





>










>





>







>

|

















>








>








>






>







<
<
<
<
<
<
<
<
<
<
<
|
<

|

|
|
>
|
>
|
|
|
|
|
|
|
|







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 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.











.\" METHOD: stat

.TP
\fBfile stat \fIname\fR ?\fIvarName\fR?
.
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
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.

.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.

.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







>








>







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
% \fBfile tempdir\fR /tmp/
/tmp/tcl_1mOJHD
% \fBfile tempdir\fR myapp
/var/tmp/myapp_0ihS0n
.CE
.RE
.VE "8.7, TIP 431"

.TP
\fBfile tempfile\fR ?\fInameVar\fR? ?\fItemplate\fR?
'\" 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


















.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.

.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.

.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
.
These commands always operate using the real user and group identifiers,
not the effective ones.
.TP
\fBWindows\fR\0\0\0\0
.
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







>


|














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>













>







|




|







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
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
.
These commands always operate using the real user and group identifiers,
not the effective ones.
.TP
\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
        windows {
            set ext .obj
        }
        unix {
           set ext .o
        }
    }
    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
.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]
.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:







|




















|









|











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] {
        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
.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 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.

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
.SH NAME
fileevent \- Execute a script when a channel becomes readable or writable
.SH SYNOPSIS
\fBfileevent \fIchannelId \fBreadable \fR?\fIscript\fR?
.sp
\fBfileevent \fIchannelId \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







<







13
14
15
16
17
18
19

20
21
22
23
24
25
26
.SH NAME
fileevent \- Execute a script when a channel becomes readable or writable
.SH SYNOPSIS
\fBfileevent \fIchannelId \fBreadable \fR?\fIscript\fR?
.sp
\fBfileevent \fIchannelId \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

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
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
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.  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







.SH "TILDE SUBSTITUTION"
.PP




In addition to the file name rules described above, Tcl also supports
\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
Unix, MacOS X and Windows (except very old releases).
.PP
Old Windows platforms do not support tilde substitution when a user name
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
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)
.SH KEYWORDS
current directory, absolute file name, relative file name,
volume-relative file name, portability
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:







>






>
|









>



>




>



>



>




>





>













>






>




>




>




>




>




>
>
>
>
>
>
>


>
>
>
>
|
<
>
>
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<












|
<
<



















|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158









159
160
161
162
163
164
165
166
167
168
169
170
171


172
173
174
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
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.
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
The exception to the above is initialization of the \fBauto_path\fR variable

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
POSIX, MacOS X and Windows platforms.









.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).


.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), 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/for.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.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







<







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
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,
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.







|







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 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
.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.







<







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
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:







<


<






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
.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.







<







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
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
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
Specifies that a number should always be printed with a sign,
even if positive.
.TP 10
\fIspace\fR
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
Specifies that the number should be padded on the left with
zeroes instead of spaces.
.TP 10
\fB#\fR
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







<
|



<
|


<
|


<
|


<
|







59
60
61
62
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:

.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).

.IP \fB+\fR 10
Specifies that a number should always be printed with a sign,
even if positive.

.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.

.IP \fB0\fR 10
Specifies that the number should be padded on the left with
zeroes instead of spaces.

.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
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
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.
If it is \fBll\fR it specifies that an integer value is taken







|
|







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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
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.
If it is \fBll\fR it specifies that an integer value is taken
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
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
Convert integer to signed decimal string.
.TP 10
\fBu\fR
Convert integer to unsigned decimal string.
.TP 10
\fBi\fR
Convert integer to signed decimal string (equivalent to \fBd\fR).
.TP 10
\fBo\fR
Convert integer to unsigned octal string.
.TP 10
\fBx\fR or \fBX\fR
Convert integer to unsigned hexadecimal string, using digits
.QW 0123456789abcdef
for \fBx\fR and
.QW 0123456789ABCDEF
for \fBX\fR).
.TP 10
\fBb\fR
Convert integer to unsigned binary string, using digits 0 and 1.
.TP 10
\fBc\fR
Convert integer to the Unicode character it represents.
.TP 10
\fBs\fR
No conversion; just insert string.
.TP 10
\fBf\fR
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
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
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
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
No conversion: just insert \fB%\fR.
.TP 10
\fBp\fR
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:







<
|

<
|

<
|

<
|

<
|





<
|

<
|

<
|

<
|




<
|






<
|





<
|





<
|

<
|







143
144
145
146
147
148
149

150
151

152
153

154
155

156
157

158
159
160
161
162
163

164
165

166
167

168
169

170
171
172
173
174

175
176
177
178
179
180
181

182
183
184
185
186
187

188
189
190
191
192
193

194
195

196
197
198
199
200
201
202
203
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:

.IP \fBd\fR 10
Convert integer to signed decimal string.

.IP \fBu\fR 10
Convert integer to unsigned decimal string.

.IP \fBi\fR 10
Convert integer to signed decimal string (equivalent to \fBd\fR).

.IP \fBo\fR 10
Convert integer to unsigned octal string.

.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).

.IP \fBb\fR 10
Convert integer to unsigned binary string, using digits 0 and 1.

.IP \fBc\fR 10
Convert integer to the Unicode character it represents.

.IP \fBs\fR 10
No conversion; just insert string.

.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.

.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.

.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.

.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.

.IP \fB%\fR 10
No conversion: just insert \fB%\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
'\"
'\" Copyright (c) 2018 by Kevin B. Kenny <[email protected]>. All rights reserved
'\" Copyright (c) 2019 by 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"
.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
.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
.
\fIvalue\fR is a floating point zero.
.TP
\fBsubnormal\fR
.
\fIvalue\fR is the result of a gradual underflow.
.TP
\fBnormal\fR
.
\fIvalue\fR is an ordinary floating-point number (not zero, subnormal,
infinite, nor NaN).
.TP
\fBinfinite\fR
.
\fIvalue\fR is a floating-point infinity.
.TP
\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

|
|











|






<
|
<

<
|
<

<
|
<


<
|
<

<
|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 Kevin B. Kenny <[email protected]>. 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"
.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
.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:

.IP \fBzero\fR

\fIvalue\fR is a floating point zero.

.IP \fBsubnormal\fR

\fIvalue\fR is the result of a gradual underflow.

.IP \fBnormal\fR

\fIvalue\fR is an ordinary floating-point number (not zero, subnormal,
infinite, nor NaN).

.IP \fBinfinite\fR

\fIvalue\fR is a floating-point infinity.

.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
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 <[email protected]>. All rights reserved
.fi
'\" Local Variables:
'\" mode: nroff
'\" End:







|




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 Kevin B. Kenny <[email protected]>. All rights reserved
.fi
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/gets.n.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.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?
.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







<







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
gets \- Read a line from a channel
.SH SYNOPSIS
\fBgets \fIchannelId\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
43
44
45
46
47
48
49





































50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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} {
    puts "[incr lineNumber]: $line"
}
close $chan
.CE

.SH "SEE ALSO"
file(n), eof(n), fblocked(n), Tcl_StandardChannels(3)

.SH KEYWORDS
blocking, channel, end of file, end of line, line, non-blocking, read
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












<


<






42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

98
99

100
101
102
103
104
105
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 "ENCODING ERRORS"
.PP
Encoding errors may exist, if the encoding profile \fBstrict\fR is used.
Encoding errors are special, as an eventual introspection or  recovery is
possible by changing to an encoding which accepts the data.
An encoding error is reported by the POSIX error code \fBEILSEQ\fR.
The file pointer is unchanged in the error case.
.PP
Here is an example with an encoding error in UTF-8 encoding, which is then
introspected by a switch to the binary encoding. The test file contains a not
continued multi-byte sequence at position 1 (\fBA \\xC3 B\fR):
.PP
File creation for example
.CS
% set f [open test_A_195_B.txt wb]; puts -nonewline $f A\\xC3B; close $f
.CE
Encoding error example
.CS
% set f [open test_A_195_B.txt r]
file384b6a8
% fconfigure $f -encoding utf-8 -profile strict
% catch {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
% tell $f
0
% fconfigure $f -encoding binary -profile strict
% gets $f
AÃB
.CE
Compared to \fBread\fR, any already decoded data is not consumed.
The file position is still at 0 and the recovery \fBgets\fR returns also the
already well decoded leading data.
.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} {
    puts "[incr lineNumber]: $line"
}
close $chan
.CE

.SH "SEE ALSO"
file(n), eof(n), fblocked(n), Tcl_StandardChannels(3)

.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
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:

.TP
\fB\-directory\fR \fIdirectory\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.

.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.

.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.

.TP
\fB\-path\fR \fIpathPrefix\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.

.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"
will return paths like \fBfoo.aux foo.bib foo.tex\fR etc.

.TP
\fB\-types\fR \fItypeList\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),







>

|







>






>



|
|
>

|











>











|

>

|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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\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; This is the
default behavior in Tcl 9.0, so this switch has no effect any more.
.\" OPTION: -path
.TP
\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 /home/fred/foo.tex] .*\fR"
will return paths like \fBfoo.aux foo.bib foo.tex\fR etc.
.\" OPTION: -types
.TP
\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),
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
\fBglob */\fR
.CE
.PP
except that the first case doesn't return the trailing
.QW /
and is more platform independent.
.RE

.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
.
Matches any single character.
.TP 10
\fB*\fR
.
Matches any sequence of zero or more characters.
.TP 10
\fB[\fIchars\fB]\fR
.
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
.
Matches the character \fIx\fR.
.TP 10
\fB{\fIa\fB,\fIb\fB,\fI...\fR}
.
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







>










<
|
<

<
|
<

<
|
<



<
|
<

<
|
<







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

136

137

138

139

140

141
142
143

144

145

146

147
148
149
150
151
152
153
\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:

.IP \fB?\fR 10

Matches any single character.

.IP \fB*\fR 10

Matches any sequence of zero or more characters.

.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.

.IP \fB\e\fIx\fR 10

Matches the character \fIx\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
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
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







<
<
<
<
<
<
<
<
<
<







<
<
<
<
<
<
<
<
<
<



|
<
<
<
<
<
<







161
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.










.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.










.SH "WINDOWS PORTABILITY ISSUES"
.PP
For Windows UNC names, the servername and sharename components of the path
may not contain ?, *, or [] constructs.






.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
\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
.CE
.PP
Find all subdirectories of the current directory:
.PP
.CS
\fBglob\fR \-type d *
.CE







|







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 [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
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.

.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.

.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.

.TP
\fBhistory clear\fR

Erase the history list.  The current keep limit is retained.
The history event numbers are reset.

.TP
\fBhistory event\fR ?\fIevent\fR?

Returns the value of the event given by \fIevent\fR.  \fIEvent\fR
defaults to \fB\-1\fR.

.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.

.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.

.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.

.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.
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







<
>
|
>


>




>


>







>


>


>


>


>


>




>


>



>


>



>


>













|
|







33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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.
.\" 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 \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
'\"
'\" Copyright (c) 1995-1997 Sun Microsystems, Inc.
'\" Copyright (c) 1998-2000 by 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"
.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

\fBpackage require http\fI ?\fB2.9\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 ...?
.sp
\fB::http::quoteString\fR \fIvalue\fR
.sp
\fB::http::reset\fR \fItoken\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
.sp
\fB::http::ncode \fItoken\fR
.sp
\fB::http::meta \fItoken\fR
.sp
\fB::http::data \fItoken\fR


.sp
\fB::http::error \fItoken\fR
.sp
\fB::http::cleanup \fItoken\fR


.sp

\fB::http::register \fIproto port command\fR
.sp
\fB::http::registerError \fIport\fR ?\fImessage\fR?
.sp
\fB::http::unregister \fIproto\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.

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
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
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.













.SH COMMANDS

.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

.TP
\fB\-accept\fR \fImimetypes\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/*" .

.TP
\fB\-cookiejar\fR \fIcommand\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

.TP
\fB\-pipeline\fR \fIboolean\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.

.TP
\fB\-postfresh\fR \fIboolean\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.

.TP
\fB\-proxyhost\fR \fIhostname\fR
.


The name of the proxy host, if any.  If this value is the
empty string, the URL host is contacted directly.
.TP
\fB\-proxyport\fR \fInumber\fR
.


The proxy port number.
.TP
\fB\-proxyfilter\fR \fIcommand\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.






.TP























\fB\-repost\fR \fIboolean\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.

.TP




















\fB\-urlencoding\fR \fIencoding\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
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
.
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" .
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.

.TP
\fB\-zip\fR \fIboolean\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.

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.
.RE

.TP
\fB::http::geturl\fR \fIurl\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\-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
\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

.TP
\fB\-binary\fR \fIboolean\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
considered binary data).

.TP
\fB\-blocksize\fR \fIsize\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).

.TP
\fB\-channel\fR \fIname\fR
.
Copy the URL contents to channel \fIname\fR instead of saving it in
\fBstate(body)\fR.


.TP
\fB\-command\fR \fIcallback\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
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


}
.CE





.RE

.TP















\fB\-handler\fR \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
\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
    # 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 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").



.PP

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.







.RE

.TP
\fB\-headers\fR \fIkeyvaluelist\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

.TP
\fB\-keepalive\fR \fIboolean\fR
.
If boolean \fBtrue\fR, attempt to keep the connection open for servicing
multiple requests.  Default is 0.

.TP
\fB\-method\fR \fItype\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.












.TP
\fB\-myaddr\fR \fIaddress\fR
.
Pass an specific local address to the underlying \fBsocket\fR call in case
multiple interfaces are available.

.TP
\fB\-progress\fR \fIcallback\fR
.

The \fIcallback\fR is made after each transfer of data from the URL.


The callback gets three additional arguments: the \fItoken\fR 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
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



}
.CE
.RE

.TP
\fB\-protocol\fR \fIversion\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.

.TP
\fB\-query\fR \fIquery\fR
.

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.


.TP
\fB\-queryblocksize\fR \fIsize\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).

.TP
\fB\-querychannel\fR \fIchannelID\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
in order to create that header.  If it is
unable to determine the size, it returns an error.

.TP
\fB\-queryprogress\fR \fIcallback\fR
.

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).

.TP
\fB\-strict\fR \fIboolean\fR
.


Whether to enforce RFC 3986 URL validation on the request.  Default is 1.

.TP
\fB\-timeout\fR \fImilliseconds\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

after a timeout has occurred.

.TP
\fB\-type\fR \fImime-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.

.TP
\fB\-validate\fR \fIboolean\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.
.RE

.TP
\fB::http::formatQuery\fR \fIkey 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.

.TP
\fB::http::quoteString\fR \fIvalue\fR
.
This procedure does x-url-encoding of string.  It takes a single argument and
encodes it.

.TP
\fB::http::reset\fR \fItoken\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.

.TP
\fB::http::wait\fR \fItoken\fR
.
This is a convenience procedure that 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.

.TP
\fB::http::data\fR \fItoken\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 is a convenience procedure that returns the \fBerror\fR element
of the state array.
.TP

\fB::http::status\fR \fItoken\fR
.
This is a convenience procedure that returns the \fBstatus\fR element of
the state array.
.TP
\fB::http::code\fR \fItoken\fR
.
This is a convenience procedure that returns the \fBhttp\fR element of the

state array.
.TP
\fB::http::ncode\fR \fItoken\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.


.TP
\fB::http::size\fR \fItoken\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.
.TP

\fB::http::meta\fR \fItoken\fR
.



This is a convenience procedure that returns the \fBmeta\fR
element of the state array which contains the HTTP response
headers. See below for an explanation of this element.

.TP
\fB::http::cleanup\fR \fItoken\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
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.





































































































































































.TP
\fB::http::register\fR \fIproto port command\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.:



























.RS
.PP
.CS
package require http
package require tls

::http::register https 443 ::tls::socket

set token [::http::geturl https://my.secure.site/]
.CE
.RE


.TP
\fB::http::registerError\fR \fIport\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.

.TP
\fB::http::unregister\fR \fIproto\fR
.
This procedure unregisters a protocol handler that was previously
registered via \fB::http::register\fR, returning a two-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.




















.SH ERRORS
The \fB::http::geturl\fR procedure will raise errors in the following cases:
invalid command line options,
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




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,
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






callback does.


.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.


These are described below.
.TP
\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
procedure returns a value like
.QW "HTTP 404 File not found" .
.TP
\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.










.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 is unable to
write all the post query data to the server before the server

responds and closes the socket.
The error message is saved in the \fBposterror\fR status array


element and then  \fB::http::geturl\fR attempts to complete the

transaction.
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:
.PP
.CS
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.

The following elements of
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.
.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
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
.
The current number of bytes fetched from the URL.
This value is returned by the \fB::http::size\fR command.
.TP
\fBerror\fR
.
If defined, this is the error string seen when the HTTP transaction
was aborted.
.TP

\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:
.RS
.PP
.CS
\fIHTTP/1.1 code string\fR
.CE
.PP
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
\fBLocation\fR meta-data specifies a new URL that contains the

requested information.
.RE
.TP
\fBmeta\fR
.

The HTTP protocol returns meta-data that describes the URL contents.
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
.PP
.CS
array set meta $state(meta)
.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
.
The type of the URL contents.  Examples include \fBtext/html\fR,
\fBimage/gif,\fR \fBapplication/postscript\fR and
\fBapplication/x-tcl\fR.
.TP


\fBContent-Length\fR
.
The advertised size of the contents.  The actual size obtained by
\fB::http::geturl\fR is available as \fBstate(currentsize)\fR.
.TP


\fBLocation\fR
.
An alternate URL that contains the requested data.
.RE
.TP
\fBposterror\fR
.
The error, if any, that occurred while writing
the post query data to the server.
.TP
\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
.

A copy of the \fBContent-Length\fR meta-data value.
.TP

\fBtype\fR
.
A copy of the \fBContent-Type\fR meta-data value.
.TP

\fBurl\fR
.
The requested URL.

.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
pipelining where permitted if the \fBhttp::config\fR option
\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.


|





|






>
|

|

<

<
|
<
|
<
|
<

<

<

<
|
<
|
<
|
<
|
>
>
|
|
<
|
>
>
|
>
|
<
|
<

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|
>












|
|
<




|




>
>
>
>
>
>
>
>
>
>
>
>
>

>











>

|






>

|







>

|




>

|


|
|
|
>

|

>
>
|
|
<
|
<
>
>
|

|






|
|
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|










>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|



|
|
<
<
<
<

|








>

|


|
|
>

|
|

>

|


|


|
|






>

|



|

>

|




>

|


<
>
>

|

<
|
>
>
|







|
|
>
>


>
>
>
>
>

>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
|
>
|
|








|
|









>
>
|
>
>
>

>
|
>
>
>
>
>
>
>

>

|















>

|



>

|


|
|
>
>
>
>
>
>
>
>
>
>
>
>

|



>

|

>
|
>
>
|

|
>
>
|






|
>
>
>



>

|




>

|

>
|
>
>
>
>
|
>
>
>
>
>
|
|
>
>

|







>

|





|
|


>

|

>
|
>
|
|
>

|

>
>
|
>

|





|
>

>

|




>

|


|
>
|
|
|

>

|






>

|



>

|




>

|

|






>

|

<
|
|
>
>
|
|
<
<
|
>
|
|
<
|

|

|
>
|

|

|
|
>
>

|

<
<
|
<
>
|
<
>
>
>
|
|
<
>

|



|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|



|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|




>
>

|









>

|


|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
<
<


<
<

|
>
>
>
>











|
<




>
>
>
>
>
>
|
>
>





|
>
>

<
|
<

|
|
|


<
|
<


>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
<
>
|
<
>
>
|
>
|
<
<
<

|
>
|
>
>
>
>
>
>
|


|





>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
|
<
<
<
<
<
|
>
>
>
>
>
>
>
>
>
>
|
<
<
|
<
|
<
<
<
<
>
|
<
<
|
<
<
|
|
|
|
<
<
|
<
>
|
<
|
|
|
>
|
<
|
|
|
<
<
|
<
<
<
<
<
|
<
<
|
|
<
>
>
|
<
<
|
<
>
>
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
>
|
<
>
|
<
>
|
<
|
|
>
|
<
<
>



















|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21

22

23

24

25

26

27

28

29

30

31
32
33
34
35

36
37
38
39
40
41

42

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

161

162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255




256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 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.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\fR ?\fB2.10\fR?
.\" See Also -useragent option documentation in body!

\fB::http::config\fR ?\fI\-option value\fR ...?

\fB::http::geturl \fIurl\fR ?\fI\-option value\fR ...?

\fB::http::formatQuery\fI key value\fR ?\fIkey value\fR ...?

\fB::http::quoteString\fI value\fR

\fB::http::reset\fI token\fR ?\fIwhy\fR?

\fB::http::wait \fItoken\fR

\fB::http::status \fItoken\fR

\fB::http::size \fItoken\fR

\fB::http::error \fItoken\fR

\fB::http::postError \fItoken\fR

\fB::http::cleanup \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

\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?

\fB::http::registerError \fIsock\fR ?\fImessage\fR?

\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 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 token can be supplied as an argument to other commands, to manage the
transaction and examine its results.

.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 \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\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\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\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\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.
.\" OPTION: -proxyauth
.TP
\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
Authentication.  If the proxy server requires authentication by another
technique, e.g. Digest Authentication, the \fB\-proxyauth\fR option is not

useful.  In that case the caller must expect a 407 response from the proxy,

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\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 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\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\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.
.\" OPTION: -useragent




.TP
\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" .
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\fI boolean\fR
.
If the value is boolean \fBtrue\fR, then by default requests will send a header
.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 value is 1.
.RE
.\" COMMAND: geturl
.TP
\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 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 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\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 \fBdeflate\fR is
considered binary data).
.\" OPTION: -blocksize
.TP
\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\fI name\fR
.
Copy the URL contents to channel \fIname\fR instead of saving it in

a Tcl variable for retrieval by \fB::http::responseBody\fR.
.\" OPTION: -command
.TP
\fB\-command\fI callback\fR
.

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 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\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.
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 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
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
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\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\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\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 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\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\fI callback\fR
.
If the \fB\-progress\fR option is present,
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 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
    # Access state as a Tcl array defined in this proc
    ...
    return
}
.CE
.RE
.\" OPTION: -protocol
.TP
\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\fI query\fR
.
This flag (if the value is non-empty) causes \fB::http::geturl\fR to do a
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\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\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 \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\fI callback\fR
.
If the \fB\-queryprogress\fR option is present,
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\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
be encoded to "%20").  Default value is 1.
.\" OPTION: -timeout
.TP
\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 (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\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\fI boolean\fR
.
If \fIboolean\fR is non-zero, then \fB::http::geturl\fR does an HTTP HEAD
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\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\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\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\fI token\fR
.
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::status\fI token\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


.RS
The name "status" is not related to the terms "status line" and
"status code" that are defined for a HTTP response.
.RE

.\" COMMAND: size
.TP
\fB::http::size\fI token\fR
.
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::error\fI token\fR
.
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::postError\fI token\fR
.


A POST request is a call to \fB::http::geturl\fR with either

the \fB\-query\fR or \fB\-querychannel\fR option.
The \fB::http::postError\fR command returns the error information generated

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.

.\" COMMAND: cleanup
.TP
\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::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\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. 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 ::tls::socketCmd 1 1

set token [::http::geturl https://my.secure.site/]
.CE
.RE
.RE
.\" COMMAND: registerError
.TP
\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\fI proto\fR
.
This procedure unregisters a protocol handler that was previously
registered via \fB::http::register\fR, returning a six-item list of

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,
or an invalid URL.


These errors mean that it
cannot even start the network transaction.


For synchronous \fB::http::geturl\fR calls (where \fB\-command\fR is
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::responseInfo\fR to check the transaction status.

.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
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 (or the value
of the \fIstatus\fR key in the dictionary returned
by \fB::http::responseInfo\fR).
These are described below.

.IP \fBok\fR

If the HTTP transaction completes entirely, then status will be \fBok\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" .

.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.
.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
supplied to \fB::http::geturl\fR and \fB::http::config\fR.  However, it is

sometimes helpful to examine what \fB::http::geturl\fR actually sent to the
server, and this information is available through

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.



.SH "STATE ARRAY"
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
.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 array are supported, and are the origin of the














values returned by commands as described below.  When a dictionary key is




mentioned below, this refers to the \fBdict\fR value returned by
command \fB::http::responseInfo\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


For command \fB::http::size\fR; and for dictionary key \fIcurrentSize\fR.

.IP \fBerror\fR




For command \fB::http::error\fR; part is used in dictionary key \fIerror\fR.
.IP \fBhttp\fR


For command \fB::http::responseLine\fR.


.IP \fBhttpResponse\fR
For dictionary key \fIhttpResponse\fR.
.IP \fBmeta\fR
For command \fB::http::responseHeaders\fR. Further discussion above in the


section \fBMORE METADATA\fR.

.IP \fBmethod\fR
For dictionary key \fImethod\fR.

.IP \fBposterror\fR
For dictionary key \fIpostError\fR.
.IP \fBpostErrorFull\fR
For command \fB::http::postError\fR.
.IP \fB\-protocol\fR

For dictionary key \fIhttpRequest\fR.
.IP \fBquerylength\fR
For dictionary key \fItotalPost\fR.


.IP \fBqueryoffset\fR





For dictionary key \fIcurrentPost\fR.


.IP \fBreasonPhrase\fR
For dictionary key \fIreasonPhrase\fR.

.IP \fBrequestHeaders\fR
For command \fB::http::requestHeaders\fR.
.IP \fBrequestLine\fR


For command \fB::http::requestLine\fR.

.IP \fBresponseCode\fR
For dictionary key \fIresponseCode\fR.
.IP \fBstate\fR




For dictionary key \fIstage\fR.




.IP \fBstatus\fR






For command \fB::http::status\fR; and for dictionary key \fIstatus\fR.
.IP \fBtotalsize\fR

For dictionary key \fItotalSize\fR.
.IP \fBtransfer\fR

For dictionary key \fItransferEncoding\fR.
.IP \fBtype\fR

For dictionary key \fIcontentType\fR.
.IP \fBupgrade\fR
For dictionary key \fIupgrade\fR.
.IP \fBurl\fR


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
pipelining where permitted if the \fBhttp::config\fR option
\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
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.
.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
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,
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.
.PP
Option \fB-pipeline\fR, if boolean \fBtrue\fR, will pipeline GET and HEAD 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.

.PP
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
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.
.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
.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).

.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

.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
.
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
.
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
.
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
.
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
.
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
.
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
.
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
.
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
.
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 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.
.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
    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







|
|



















|







|





|
|

|
<
|
>





|
|
>

|




|

|
|







|











>
















>








<
|
<





<
|
<






<
|
<


<
|
<


<
|
<



<
|
<



<
|
<


<
|
<


<
|
<







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|











|







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.
.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
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,
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.
.PP
Option \fB\-pipeline\fR, if boolean \fBtrue\fR, will pipeline GET and HEAD

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.
.PP
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 \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.
.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 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

.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.

.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.

.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).

.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.

.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.

.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.

.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.

.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).

.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 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
    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
'\" 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 version\fR
.fi

.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.)

.TP
\fBtcl::idna decode\fR \fIhostname\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.

.TP
\fBtcl::idna encode\fR \fIhostname\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.

.TP
\fBtcl::idna puny\fR \fIsubcommand ...\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?
.
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?
.
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

.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:







|
|
|
|


>




>

|






>

|




>

|





|







|







>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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\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\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\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\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\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\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
.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







<







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
info \- Information about the state of the Tcl interpreter
.SH SYNOPSIS
\fBinfo \fIoption \fR?\fIarg arg ...\fR?
.BE
.SH DESCRIPTION
.PP
Available commands:

.TP
\fBinfo args \fIprocname\fR
.
Returns the names of the parameters to the procedure named \fIprocname\fR.

.TP
\fBinfo body \fIprocname\fR
.
Returns the body of the procedure named \fIprocname\fR.

.TP
\fBinfo class\fI subcommand class\fR ?\fIarg ...\fR
.
Returns information about the class named \fIclass\fR.
See \fBCLASS INTROSPECTION\fR below.

.TP
\fBinfo cmdcount\fR
.
Returns the total number of commands evaluated in this interpreter.

.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







>




>




>





>




>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82

83
84
85
86
87
88
















89
90
91
92
93
94

95
96
97
98
99
100

101
102
103
104
105
106
107
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

.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.

.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.
















.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.

.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.

.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







<
<


>








>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>






>







69
70
71
72
73
74
75


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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.


.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
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

.TP
\fBinfo exists \fIvarName\fR
.
Returns \fB1\fR if a variable named \fIvarName\fR is visible and has been
defined, and \fB0\fR otherwise.

.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







>





>







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
.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
.
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
.
A script loaded via the \fBsource\fR
command.
.TP
\fBproc\fR\0\0\0\0\0\0\0\0
.
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
.
The body of a script provided to \fBeval\fR or \fBuplevel\fR.
.TP
\fBprecompiled\fR\0\0\0\0\0\0\0\0
.
A pre-compiled script (loadable by the package
\fBtbcload\fR), and no further information is available.
.RE
.TP
\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
.
For type \fBsource\fR, provides the normalized path of the file that contains
the command.
.TP
\fBcmd\fR
.
The command before substitutions were performed.
.TP
\fBproc\fR
.
For type \fBprod\fR, the name of the procedure containing the command.
.TP
\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
.
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







<
|
<



<
|
<
|
<
<
|
<


<
|
<

<
|
<
|


<
|
<




<
|
<


<
|
<

<
|
<

<
|
<


<
|
<







172
173
174
175
176
177
178

179

180
181
182

183

184


185

186
187

188

189

190

191
192
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:

.IP \fBtype\fR

Always present.  Possible values are \fBsource\fR, \fBproc\fR,
\fBeval\fR, and \fBprecompiled\fR.
.RS

.IP \fBsource\fR

A script loaded via the \fBsource\fR command.


.IP \fBproc\fR

The body of a procedure that could not be traced back to a
line in a particular script.

.IP \fBeval\fR

The body of a script provided to \fBeval\fR or \fBuplevel\fR.

.IP \fBprecompiled\fR

A precompiled script (loadable by the package
\fBtbcload\fR), and no further information is available.
.RE

.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.

.IP \fBfile\fR

For type \fBsource\fR, provides the normalized path of the file that contains
the command.

.IP \fBcmd\fR

The command before substitutions were performed.

.IP \fBproc\fR

For type \fBprod\fR, the name of the procedure containing the command.

.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.

.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
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

.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.

.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.

.TP
\fBinfo hostname\fR
.
Returns the name of the current host.


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.


.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
list.  See \fBuplevel\fR for more information on levels.

.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.

.TP
\fBinfo loaded \fR?\fIinterp\fR? ?\fIpackage\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
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.

.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.

.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.

.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.

.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.

.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.

.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.

.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.

.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.

.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.


.SS "CLASS INTROSPECTION"
.PP
The following \fIsubcommand\fR values are supported by \fBinfo class\fR:

.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







>







>









>




|
>





>
>







|

>





>








>







|





>





>





>








>








>






>





>









|
>
|
>
>



>







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 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?
.
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
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.
.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
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

.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.

.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.

.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

.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.

.TP
\fBinfo class filters\fI class\fR
.
This subcommand returns the list of filter methods set on the class.

.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.

.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.

.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

.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.

.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

.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.
.IP \fBunexported\fR 3
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.
.RE
.VE TIP500
.RE

.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.

.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.




























.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.

.TP
\fBinfo class superclasses\fI class\fR
.
This subcommand returns a list of direct superclasses of class \fIclass\fR in
inheritance precedence order.

.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:

.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







>









>








>


















>





>




>





>






>







>










>














>








|
|

|
|

|
|



>








>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>





>













>







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.
.IP \fBunexported\fR 3
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.
.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
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

.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.

.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

.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.

.TP
\fBinfo object filters\fI object\fR
.
This subcommand returns the list of filter methods set on the object.

.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.

.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







>






>












>








>




>





>







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
.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

.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

.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.

.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

.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.
.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.
.RE
.VE TIP500
.RE

.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.

.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.

.TP
\fBinfo object namespace\fI object\fR
.
This subcommand returns the name of the internal namespace of the object named
\fIobject\fR.

.TP




























\fBinfo object variables\fI object\fRR ?\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

.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







>







>










>














>











|
|

|
|



>








>





>





>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|








>







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.
.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.
.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\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
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:

.TP
\fBinterp\fR \fBalias\fR \fIsrcPath\fR \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 name of the source command in the
child is different from \fIsrcToken\fR).
.TP
\fBinterp\fR \fBalias\fR \fIsrcPath\fR \fIsrcToken\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?
.
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.







>

|







|







|







83
84
85
86
87
88
89
90
91
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 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 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 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
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.

.TP
\fBinterp\fR \fBaliases \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).

.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.

.TP
\fBinterp\fR \fBcancel \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.

.TP







\fBinterp\fR \fBcreate \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







>

|






>









>

|
>












>

>
>
>
>
>
>
>
|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
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 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 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 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
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.

.TP
\fBinterp\fR \fBdebug \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







>

|







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 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
\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

.TP
\fBinterp\fR \fBdelete \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.

.TP
\fBinterp\fR \fBeval\fR \fIpath 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.


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.


.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.

.TP
\fBinterp expose \fIpath\fR \fIhiddenName\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.

.TP
\fBinterp\fR \fBhide\fR \fIpath\fR \fIexposedCmdName\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.

.TP
\fBinterp\fR \fBhidden\fR \fIpath\fR
.
Returns a list of the names of all hidden commands in the interpreter
identified by \fIpath\fR.

.TP
\fBinterp\fR \fBinvokehidden\fR \fIpath\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.


Note that the hidden command will be executed (by default) in the
current context stack frame of the \fIpath\fR interpreter.

Hidden commands are explained in more detail in \fBHIDDEN COMMANDS\fR, below.


.TP
\fBinterp issafe\fR ?\fIpath\fR?
.
Returns \fB1\fR if the interpreter identified by the specified \fIpath\fR
is safe, \fB0\fR otherwise.

.TP
\fBinterp\fR \fBlimit\fR \fIpath\fR \fIlimitType\fR ?\fI\-option\fR? ?\fIvalue\fR \fI...\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.

.TP
\fBinterp marktrusted\fR \fIpath\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.

.TP
\fBinterp\fR \fBrecursionlimit\fR \fIpath\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

.TP
\fBinterp\fR \fBshare\fR \fIsrcPath channelId destPath\fR
.
Causes the IO channel identified by \fIchannelId\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?
.
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
.
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.

.TP
\fBinterp\fR \fBtransfer\fR \fIsrcPath channelId destPath\fR
.
Causes the IO channel identified by \fIchannelId\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:

.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).

.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







>

|






>

|







>
>





>
>






>

|









>

|














>

|



>

|

















>
>


>

>
>





>

|








>

|






>

|


















>

|








<
<
|
<
<
<

|









>

|



















>







>







243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 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 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 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 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 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 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 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\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 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 share\fI srcPath channelId destPath\fR
.
Causes the IO channel identified by \fIchannelId\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.


.\" METHOD: target



.TP
\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 transfer\fI srcPath channelId destPath\fR
.
Causes the IO channel identified by \fIchannelId\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
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.

.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.

.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.


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.


.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.

.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.

.TP
\fIchild \fBhidden\fR
.
Returns a list of the names of all hidden commands in \fIchild\fR.

.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.


Note that the hidden command will be executed (by default) in the
current context stack frame of \fIchild\fR.

For more details on hidden commands,
see \fBHIDDEN COMMANDS\fR, below.


.TP
\fIchild \fBissafe\fR
.
Returns  \fB1\fR if the child interpreter is safe, \fB0\fR otherwise.

.TP
\fIchild \fBlimit\fR \fIlimitType\fR ?\fI\-option\fR? ?\fIvalue\fR \fI...\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.

.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.

.TP
\fIchild\fR \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







>









>









>
>





>
>










>















>




>


















>
>


>
|
<
>
>



|
>

|








>







>

|







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, see \fBHIDDEN COMMANDS\fR, below.

.RE
.\" METHOD: issafe
.TP
\fIchild \fBissafe\fR
.
Returns \fB1\fR if the child interpreter is safe, \fB0\fR otherwise.
.\" METHOD: limit
.TP
\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 \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
\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
.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







|
|
|
|
|
|
|
|
|
|







630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
\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	\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
.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
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
\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.

.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).


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.


.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.

.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.)

.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.

.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

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
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.







>










>
>



>
>








>







>









>



















|
|
>




|
|







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
\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
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
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
    set x 0
    while {1} {
        puts "Counting up... [incr x]"
    }
}
.CE
.SH "SEE ALSO"

bgerror(n), load(n), safe(n), Tcl_CreateChild(3), Tcl_Eval(3), Tcl_BackgroundException(3)
.SH KEYWORDS
alias, parent interpreter, safe interpreter, child interpreter
'\"Local Variables:
'\"mode: nroff
'\"End:







>
|





952
953
954
955
956
957
958
959
960
961
962
963
964
965
    set x 0
    while {1} {
        puts "Counting up... [incr x]"
    }
}
.CE
.SH "SEE ALSO"
bgerror(n), load(n), safe(n),
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
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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
append, element, list, variable
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:







|

|






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), ledit(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)
.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
.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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
assign, element, list, multiple, set, variable
'\"Local Variables:
'\"mode: nroff
'\"End:







|

|





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), ledit(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)
.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 <[email protected]>.  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 8.7 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.

21
22
23
24
25
26
27






28
29
30
31
32
33
34
\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






.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







>
>
>
>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
\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
\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:

.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.






















.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.





.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
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.






.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







>


>












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>







>
>
>
>
>


>




|


















>
>
>
>
>
>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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 \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
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

.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.

.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

.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.

.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.













.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.

.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.














.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.

.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.

.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.







































.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"

.TP
\fBauto_execs\fR

Used by \fBauto_execok\fR to record information about whether
particular commands exist as executable files.





.TP
\fBauto_index\fR

Used by \fBauto_load\fR to save the index information read from
disk.





.TP
\fBauto_noexec\fR

If set to any value, then \fBunknown\fR will not attempt to auto-exec
any commands.

.TP
\fBauto_noload\fR

If set to any value, then \fBunknown\fR will not attempt to auto-load
any commands.

.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.













.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.







.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.









.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.

.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".


.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".

.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:







>








>


>

















>


>




















>


>






>
>
>
>
>
>
>
>
>
>
>
>
>


>








>


>





>
>
>
>
>
>
>
>
>
>
>
>
>
>


>




>


>





>


>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>


>


>
>
>
>
>


>


>
>
>
>
>


>


>


>


>













>
>
>
>
>
>
>
>
>
>
>
>
>


>





>
>
>
>
>
>
>


>






>
>
>
>
>
>
>
>
>




>


>



|
>
>


>



|
>







185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 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 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
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
'\" Copyright (c) 2001 by Kevin B. Kenny <[email protected]>.  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



|







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 Kevin B. Kenny <[email protected]>.  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
\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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, index, list
'\"Local Variables:
'\"mode: nroff
'\"End:







|

|






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), ledit(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, 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
.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

\fBlink\fR \fImethodName\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







|

|







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 tcl::oo

\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
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
        \fBlink\fR {bar Foo}
        # The method foo is now directly accessible as bar
        \fBlink\fR {::ExternalCall Foo}
        # 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\(-> Step 2:\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
.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.
    }

    method a {} {
        puts "This is a"
    }
    method b {x} {
        puts "This is b($x)"







|

|

|














|

|



|










|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
        \fBlink\fR {bar Foo}
        # The method Foo is now directly accessible as bar
        \fBlink\fR {::ExternalCall Foo}
        # 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\(-> Step 2:\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
.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 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
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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, insert, list
'\" Local Variables:
'\" mode: nroff
'\" End:







|

|






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), ledit(n), lindex(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, 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
.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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
element, list, quoting
'\"Local Variables:
'\"mode: nroff
'\"End:







|

|





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), ledit(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)
.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
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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
element, list, length
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:







|

|






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), ledit(n), lindex(n), linsert(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(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
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),
lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
foreach, iteration, list, loop, map
'\" Local Variables:
'\" mode: nroff
'\" End:







|

|





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), ledit(n), lindex(n), linsert(n), llength(n),
lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(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
.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
.br
\fBload\fR ?\fB\-global\fR? ?\fB\-lazy\fR? ?\fB\-\-\fR? \fIfileName packageName 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
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.
\fIinterp\fR is the path name of the interpreter into which to load
the package (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
is a safe one.  For normal interpreters the name of the initialization
procedure will have the form \fIpkg\fB_Init\fR, where \fIpkg\fR
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
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
initializes the safe interpreter only with partial functionality provided
by the package 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(
        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 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
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
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 \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.
.PP
If \fIfileName\fR is an empty string, then \fIpackageName\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
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
different files have been \fBload\fRed with different versions of
the package, 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.
.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
.
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>"







|

|





|



<
|

|








|

|
<
<
<
|



|
|
|

|





|




|











|



|
|
|
|


|
|
<
<
|
>
|
|
|
|
|

|

|
|


|

|







|










|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28
29
30
31
32
33
34
35
36
37
38
39
40
41



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84


85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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 prefix\fR
.br
\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 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.

\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 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
\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 \fIprefix\fB_Init\fR.  For example, if



\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 \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 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_LibraryInitProc\fR(
        Tcl_Interp *\fIinterp\fR);
.CE
.PP
The \fIinterp\fR argument identifies the interpreter in which the
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
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 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 \fIprefix\fR is omitted or specified as an empty string,
Tcl tries to guess the prefix by taking 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 \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 \fIprefix\fR must
be specified.
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
library by that name, and uses it if it is found.  If several
different files have been \fBload\fRed with different versions of
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 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
.
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
    }
}

# Now execute the command defined by the extension
foo
.CE
.SH "SEE ALSO"
info sharedlibextension, package(n), Tcl_StaticPackage(3), safe(n)
.SH KEYWORDS
binary code, dynamic library, load, safe interpreter, shared library
'\"Local Variables:
'\"mode: nroff
'\"End:







|





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_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
'\"
'\" Copyright (c) 2018 by 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"
.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".
.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 \fI$varName\fR, then an 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.

The command,
.PP
.CS
\fBlpop\fR a 1 2
.CE
.PP
gets and removes element 2 of sublist 1.

|


















|






>
|








|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 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"
.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 "\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
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, 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
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),
lmap(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, index, list, remove, pop, stack, queue
'\"Local Variables:
'\"mode: nroff
'\"End:







|

|






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), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lrange(n), lremove(n), lrepeat(n), lreplace(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
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.

Note:
.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







>
|







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 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
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),
lmap(n), lpop(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, list, range, sublist
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:







|

|







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), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lremove(n), lrepeat(n), lreplace(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.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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
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







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 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
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),
lmap(n), lpop(n), lrange(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
element, list, remove
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:







|

|






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), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lrepeat(n), lreplace(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
'\"
'\" Copyright (c) 2003 by 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


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),
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:

|


















|
>
>













|

|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 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.
.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), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lreplace(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
% 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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n),
lreverse(n), lsearch(n), lset(n), lsort(n),
string(n)
.SH KEYWORDS
element, list, replace
.\" Local variables:
.\" mode: nroff
.\" fill-column: 78
.\" End:







|

|







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), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(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
'\"
'\" Copyright (c) 2006 by 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

|







1
2
3
4
5
6
7
8
9
'\"
'\" 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
.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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lsearch(n), lset(n), lsort(n)
.SH KEYWORDS
element, list, reverse
'\" Local Variables:
'\" mode: nroff
'\" End:







|

|





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), ledit(n), lindex(n), linsert(n), llength(n),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(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
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.

.TP
\fB\-exact\fR
.
\fIPattern\fR is a literal string that is compared for exact equality
against each list element.

.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.

.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.

.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.

.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.

.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.

.TP
\fB\-not\fR
.
This negates the sense of the match, returning the index of the first
non-matching value in the list.

.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.

.TP
\fB\-ascii\fR
.
The list elements are to be examined as Unicode strings (the name is
for backward-compatibility reasons.)

.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.

.TP
\fB\-integer\fR
.
The list elements are to be compared as integers.

.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.

.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.

.TP
\fB\-decreasing\fR
.
The list elements are sorted in decreasing order.  This option is only
meaningful when used with \fB\-sorted\fR.

.TP
\fB\-increasing\fR
.
The list elements are sorted in increasing order.  This option is only
meaningful when used with \fB\-sorted\fR.

.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.

.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.

.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.

.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







>





>





>






>













>







>






>





>













>





>








>




>






>









>





>





>


>











>













>







>







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
.PP
.CS
\fBlsearch\fR -stride 2 -index 1 -all -inline {a abc b bcd c cde} *bc*
      \fI\(-> {a abc b bcd}\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), lrepeat(n), lreplace(n),
lreverse(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:







|

|







245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
.PP
.CS
\fBlsearch\fR -stride 2 -index 1 -all -inline {a abc b bcd c cde} *bc*
      \fI\(-> {a abc b bcd}\fR
.CE
.SH "SEE ALSO"
foreach(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), 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
124
125
126
127
128
129
'\"
'\" 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 8.7 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
.PP
The numeric arguments, \fIstart\fR, \fIend\fR, \fIstep\fR, and \fIcount\fR,
can also be a valid expression. the \fBlseq\fR command will evaluate the
expression (as if with \fBexpr\fR)
and use the numeric result, or return an error as with any invalid argument
value; a non-numeric expression result will result in an error.
.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
'\"
'\" Copyright (c) 2001 by Kevin B. Kenny <[email protected]>.  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

|







1
2
3
4
5
6
7
8
9
'\"
'\" Copyright (c) 2001 Kevin B. Kenny <[email protected]>.  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
.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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lsort(n)
string(n)
.SH KEYWORDS
element, index, list, replace, set
'\"Local Variables:
'\"mode: nroff
'\"End:







|

|






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), ledit(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), 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
.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
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):

.TP
\fB\-ascii\fR
.
Use string comparison with Unicode code-point collation order (the
name is for backward-compatibility reasons.)  This is the default.

.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.

.TP
\fB\-integer\fR
.
Convert list elements to integers and use integer comparison.

.TP
\fB\-real\fR
.
Convert list elements to floating-point values and use floating comparison.

.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.

.TP
\fB\-increasing\fR
.
Sort the list in increasing order
.PQ smallest "items first" .
This is the default.

.TP
\fB\-decreasing\fR
.
Sort the list in decreasing order
.PQ largest "items first" .

.TP
\fB\-indices\fR
.
Return a list of indices into \fIlist\fR in sorted order instead of
the values themselves.

.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







|






>





>










>




>




>










>






>





>





>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
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
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
.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

.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}
.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}
.CE
.PP
returns
.QW "carrot 10 banana 25 apple 50" .
.RE

.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.

.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







>

















|







|





>






>







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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}
.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}
.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
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
     {{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







|







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
     {{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
    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),
lmap(n), lpop(n), lrange(n), lremove(n), lrepeat(n), lreplace(n),
lreverse(n), lsearch(n), lset(n)
.SH KEYWORDS
element, list, order, sort
'\" Local Variables:
'\" mode: nroff
'\" End:







|

|





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), ledit(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)
.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
'\"
'\" Copyright (c) 1993 The Regents of the University of California.
'\" Copyright (c) 1994-2000 Sun Microsystems, Inc.
'\" Copyright (c) 2005 by Kevin B. Kenny <[email protected]>. 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

package require \fBTcl 8.5\fR
.sp
\fB::tcl::mathfunc::abs\fR \fIarg\fR
.br
\fB::tcl::mathfunc::acos\fR \fIarg\fR
.br
\fB::tcl::mathfunc::asin\fR \fIarg\fR
.br
\fB::tcl::mathfunc::atan\fR \fIarg\fR
.br
\fB::tcl::mathfunc::atan2\fR \fIy\fR \fIx\fR
.br
\fB::tcl::mathfunc::bool\fR \fIarg\fR
.br
\fB::tcl::mathfunc::ceil\fR \fIarg\fR
.br
\fB::tcl::mathfunc::cos\fR \fIarg\fR
.br
\fB::tcl::mathfunc::cosh\fR \fIarg\fR
.br
\fB::tcl::mathfunc::double\fR \fIarg\fR
.br
\fB::tcl::mathfunc::entier\fR \fIarg\fR
.br
\fB::tcl::mathfunc::exp\fR \fIarg\fR
.br
\fB::tcl::mathfunc::floor\fR \fIarg\fR
.br
\fB::tcl::mathfunc::fmod\fR \fIx\fR \fIy\fR
.br
\fB::tcl::mathfunc::hypot\fR \fIx\fR \fIy\fR

.br
\fB::tcl::mathfunc::int\fR \fIarg\fR
.br
.VS "8.7, TIP 521"
\fB::tcl::mathfunc::isfinite\fR \fIarg\fR
.br
\fB::tcl::mathfunc::isinf\fR \fIarg\fR
.br
\fB::tcl::mathfunc::isnan\fR \fIarg\fR
.br
\fB::tcl::mathfunc::isnormal\fR \fIarg\fR
.VE "8.7, TIP 521"
.br
\fB::tcl::mathfunc::isqrt\fR \fIarg\fR
.br
.VS "8.7, TIP 521"
\fB::tcl::mathfunc::issubnormal\fR \fIarg\fR
.br
\fB::tcl::mathfunc::isunordered\fR \fIx y\fR
.VE "8.7, TIP 521"
.br
\fB::tcl::mathfunc::log\fR \fIarg\fR
.br
\fB::tcl::mathfunc::log10\fR \fIarg\fR
.br
\fB::tcl::mathfunc::max\fR \fIarg\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathfunc::min\fR \fIarg\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathfunc::pow\fR \fIx\fR \fIy\fR
.br
\fB::tcl::mathfunc::rand\fR
.br
\fB::tcl::mathfunc::round\fR \fIarg\fR
.br
\fB::tcl::mathfunc::sin\fR \fIarg\fR
.br
\fB::tcl::mathfunc::sinh\fR \fIarg\fR
.br
\fB::tcl::mathfunc::sqrt\fR \fIarg\fR
.br
\fB::tcl::mathfunc::srand\fR \fIarg\fR
.br
\fB::tcl::mathfunc::tan\fR \fIarg\fR
.br
\fB::tcl::mathfunc::tanh\fR \fIarg\fR
.br
\fB::tcl::mathfunc::wide\fR \fIarg\fR
.sp
.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.



|











>
|
|
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
>
<
<
<

|
<
|
<
|
<
|

<
|
<

|
<
|

<
|
<
|
<
|
<
|
<
|
<

<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20

21

22

23

24

25

26

27

28

29

30

31

32

33
34



35
36

37

38

39
40

41

42
43

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 Kevin B. Kenny <[email protected]>. 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

\fB::tcl::mathfunc::abs\fI arg\fR

\fB::tcl::mathfunc::acos\fI arg\fR

\fB::tcl::mathfunc::asin\fI arg\fR

\fB::tcl::mathfunc::atan\fI arg\fR

\fB::tcl::mathfunc::atan2\fI y x\fR

\fB::tcl::mathfunc::bool\fI arg\fR

\fB::tcl::mathfunc::ceil\fI arg\fR

\fB::tcl::mathfunc::cos\fI arg\fR

\fB::tcl::mathfunc::cosh\fI arg\fR

\fB::tcl::mathfunc::double\fI arg\fR

\fB::tcl::mathfunc::entier\fI arg\fR

\fB::tcl::mathfunc::exp\fI arg\fR

\fB::tcl::mathfunc::floor\fI arg\fR

\fB::tcl::mathfunc::fmod\fI x y\fR

\fB::tcl::mathfunc::hypot\fI x y\fR
\fB::tcl::mathfunc::int\fI arg\fR



.VS "8.7, TIP 521"
\fB::tcl::mathfunc::isfinite\fI arg\fR

\fB::tcl::mathfunc::isinf\fI arg\fR

\fB::tcl::mathfunc::isnan\fI arg\fR

\fB::tcl::mathfunc::isnormal\fI arg\fR
.VE "8.7, TIP 521"

\fB::tcl::mathfunc::isqrt\fI arg\fR

.VS "8.7, TIP 521"
\fB::tcl::mathfunc::issubnormal\fI arg\fR

\fB::tcl::mathfunc::isunordered\fI x y\fR
.VE "8.7, TIP 521"

\fB::tcl::mathfunc::log\fI arg\fR

\fB::tcl::mathfunc::log10\fI arg\fR

\fB::tcl::mathfunc::max\fI arg\fR ?\fIarg\fR ...?

\fB::tcl::mathfunc::min\fI arg\fR ?\fIarg\fR ...?

\fB::tcl::mathfunc::pow\fI x y\fR

\fB::tcl::mathfunc::rand\fR

\fB::tcl::mathfunc::round\fI arg\fR

\fB::tcl::mathfunc::sin\fI arg\fR

\fB::tcl::mathfunc::sinh\fI arg\fR

\fB::tcl::mathfunc::sqrt\fI arg\fR

\fB::tcl::mathfunc::srand\fI arg\fR

\fB::tcl::mathfunc::tan\fI arg\fR

\fB::tcl::mathfunc::tanh\fI arg\fR

\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
.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"

.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.

.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].

.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].

.TP
\fBatan \fIarg\fR
.
Returns the arc tangent of \fIarg\fR, in the range [\fI\-pi/2\fR,\fIpi/2\fR]
radians.

.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}]" .

.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.

.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.

.TP
\fBcos \fIarg\fR
.
Returns the cosine of \fIarg\fR, measured in radians.

.TP
\fBcosh \fIarg\fR
.
Returns the hyperbolic cosine of \fIarg\fR.  If the result would cause
an overflow, an error is returned.

.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.

.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.

.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.

.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.

.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.

.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.

.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.

.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"

.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"

.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"

.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"

.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.

.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"

.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"

.TP
\fBlog \fIarg\fR
.
Returns the natural logarithm of \fIarg\fR.  \fIArg\fR must be a
positive value.

.TP
\fBlog10 \fIarg\fR
.
Returns the base 10 logarithm of \fIarg\fR.  \fIArg\fR must be a
positive value.

.TP
\fBmax \fIarg\fB \fI...\fR
.
Accepts one or more numeric arguments.  Returns the one argument
with the greatest value.

.TP
\fBmin \fIarg\fB \fI...\fR
.
Accepts one or more numeric arguments.  Returns the one argument
with the least value.

.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.

.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.

.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.

.TP
\fBsin \fIarg\fR
.
Returns the sine of \fIarg\fR, measured in radians.

.TP
\fBsinh \fIarg\fR
.
Returns the hyperbolic sine of \fIarg\fR.  If the result would cause
an overflow, an error is returned.

.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.

.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.

.TP
\fBtan \fIarg\fR
.
Returns the tangent of \fIarg\fR, measured in radians.

.TP
\fBtanh \fIarg\fR
.
Returns the hyperbolic tangent of \fIarg\fR.

.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 <[email protected]>.
.fi
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:







>





>





>





>





>







>








>






>




>





>








>







>





>






>





>








>








>







>







>







>







>







>








>









>





>





>





>





>





>










>





>




>





>







>






>




>




>












|





87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 Kevin B. Kenny <[email protected]>.
.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
.\"
.\" 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

package require \fBTcl 8.5\fR
.sp
\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 ?\fInumber\fR ...?
.br
\fB::tcl::mathop::*\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::/\fR \fInumber\fR ?\fInumber\fR ...?
.br
\fB::tcl::mathop::%\fR \fInumber 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
.br
\fB::tcl::mathop::>>\fR \fInumber number\fR
.br
\fB::tcl::mathop::==\fR ?\fIarg\fR ...?
.br
\fB::tcl::mathop::!=\fR \fIarg 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
.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
.br
\fB::tcl::mathop::ni\fR \fIarg list\fR
.sp
.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













>
|
|
|
<
|
<

<
|
<

<
|
<
|
<

<

<

<

<
|
<
|
<

<
|
<

<

<

<

<

<
|
<


<

<

<


<
|
<
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18

19

20

21

22

23

24

25

26

27

28

29

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

\fB::tcl::mathop::!\fI number\fR

\fB::tcl::mathop::~\fI number\fR

\fB::tcl::mathop::+\fR ?\fInumber\fR ...?

\fB::tcl::mathop::\-\fI number\fR ?\fInumber\fR ...?

\fB::tcl::mathop::*\fR ?\fInumber\fR ...?

\fB::tcl::mathop::/\fI number\fR ?\fInumber\fR ...?

\fB::tcl::mathop::%\fI number number\fR

\fB::tcl::mathop::**\fR ?\fInumber\fR ...?

\fB::tcl::mathop::&\fR ?\fInumber\fR ...?

\fB::tcl::mathop::|\fR ?\fInumber\fR ...?

\fB::tcl::mathop::^\fR ?\fInumber\fR ...?

\fB::tcl::mathop::<<\fI number number\fR

\fB::tcl::mathop::>>\fI number number\fR

\fB::tcl::mathop::==\fR ?\fIarg\fR ...?

\fB::tcl::mathop::!=\fI arg arg\fR

\fB::tcl::mathop::<\fR ?\fIarg\fR ...?

\fB::tcl::mathop::<=\fR ?\fIarg\fR ...?

\fB::tcl::mathop::>=\fR ?\fIarg\fR ...?

\fB::tcl::mathop::>\fR ?\fIarg\fR ...?

\fB::tcl::mathop::eq\fR ?\fIarg\fR ...?

\fB::tcl::mathop::ne\fI arg arg\fR

.VS "8.7, TIP461"
\fB::tcl::mathop::lt\fR ?\fIarg\fR ...?

\fB::tcl::mathop::le\fR ?\fIarg\fR ...?

\fB::tcl::mathop::gt\fR ?\fIarg\fR ...?

\fB::tcl::mathop::ge\fR ?\fIarg\fR ...?
.VE "8.7, TIP461"

\fB::tcl::mathop::in\fI arg list\fR

\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
\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:

.TP
\fB!\fR \fIboolean\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).

.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).

.TP
\fB\-\fR \fInumber\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.

.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).

.TP
\fB/\fR \fInumber\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

.TP
\fB%\fR \fInumber 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

.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:

.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.

.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.

.TP
\fB!=\fR \fIarg 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).

.TP
\fBne\fR \fIarg arg\fR
.
Returns whether the two arguments are not equal to each other using exact
string comparison.

.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.

.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.

.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.

.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.

.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"

.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"

.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"

.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:

.TP
\fB~\fR \fInumber\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.

.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.

.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.

.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.

.TP
\fB<<\fR \fInumber 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.

.TP
\fB>>\fR \fInumber 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:

.TP
\fBin\fR \fIarg list\fR
.
Returns whether the value \fIarg\fR is present in the list \fIlist\fR
(according to exact string comparison of elements).

.TP
\fBni\fR \fIarg 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







>

|





>






>

|





>






>

|














>

|
















>



















>







>






>

|




>

|



>










>










>










>










>








>








>








>












>

|




>






>






>






>

|




>

|







>

|



>

|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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!\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\-\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/\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%\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!=\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\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~\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<<\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>>\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\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\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
'\"
'\" Copyright (c) 1992-1999 by Karl Lehenbauer and Mark Diekhans
'\" Copyright (c) 2000 by 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.

.TP
\fBmemory active\fR \fIfile\fR
.
Write a list of all currently allocated memory to the specified \fIfile\fR.

.TP
\fBmemory break_on_malloc\fR \fIcount\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.

.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.

.TP
\fBmemory init \fR[\fBon\fR|\fBoff\fR]
.
Turn on or off the pre-initialization of all allocated memory
with bogus bytes.  Useful for detecting the use of uninitialized
values.

.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.

.TP
\fBmemory onexit\fR \fIfile\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.

.TP
\fBmemory tag\fR \fIstring\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.

.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

.TP
\fBmemory trace_on_at_malloc\fR \fIcount\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.

.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

|
|

















>

|


>

|






>








>



|


>






>

|




>

|







>
















>

|










>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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 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\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\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 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\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\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\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
'\"
'\" 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

\fBpackage require Tcl 8.7\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
.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?
.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?
.sp
\fB::msgcat::mcforgetpackage\fR
.VE "TIP 412"
.sp
.VS "TIP 499"
\fB::msgcat::mcutil subcommand\fR ?\fIlocale\fR?
.VS "TIP 499"

.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.
.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.
.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.

.PP
.VS tip490
Object oriented programming is supported by the use of a package namespace.
.VE tip490
.PP
.SH COMMANDS

.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.













>
|
<

|

<

<

|

<



<

<



<



<

<

<

<

<

<

<


<
|
<


<



>













|
|

|
>
|
|

|
>






>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18

19

20
21
22

23
24
25

26

27
28
29

30
31
32

33

34

35

36

37

38

39
40

41

42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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 msgcat 1.7\fR

\fB::msgcat::mc \fIsrc-string\fR ?\fIarg arg ...\fR?

\fB::msgcat::mcmax ?\fIsrc-string src-string ...\fR?

.VS "TIP 412"
\fB::msgcat::mcexists\fR ?\fB\-exactnamespace\fR? ?\fB\-exactlocale\fR? \fIsrc-string\fR
.VE "TIP 412"

.VS "TIP 490"
\fB::msgcat::mcpackagenamespaceget\fR
.VE "TIP 490"

\fB::msgcat::mclocale \fR?\fInewLocale\fR?

.VS "TIP 499"
\fB::msgcat::mcpreferences\fR ?\fIlocale preference\fR? ...
.VE "TIP 499"

.VS "TIP 412"
\fB::msgcat::mcloadedlocales subcommand\fR ?\fIlocale\fR?
.VE "TIP 412"

\fB::msgcat::mcload \fIdirname\fR

\fB::msgcat::mcset \fIlocale src-string \fR?\fItranslate-string\fR?

\fB::msgcat::mcmset \fIlocale src-trans-list\fR

\fB::msgcat::mcflset \fIsrc-string \fR?\fItranslate-string\fR?

\fB::msgcat::mcflmset \fIsrc-trans-list\fR

\fB::msgcat::mcunknown \fIlocale src-string\fR ?\fIarg arg ...\fR?

.VS "TIP 412"
\fB::msgcat::mcpackagelocale subcommand\fR ?\fIlocale\fR?

\fB::msgcat::mcpackageconfig subcommand\fI option\fR ?\fIvalue\fR?

\fB::msgcat::mcforgetpackage\fR
.VE "TIP 412"

.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 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.
.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.
.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
\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"
.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.

.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.
.RE
.PP

.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"
.TP
\fB::msgcat::mcexists\fR ?\fB-exactnamespace\fR? ?\fB-exactlocale\fR? ?\fB-namespace\fR \fInamespace\fR? \fIsrc-string\fR
.
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.

.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).


.PP
.VE "TIP 412"
.VS "TIP 490"
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"
.TP
\fB::msgcat::mcpackagenamespaceget\fR
.
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:

.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"

.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.
.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.

.PP

The same result may be acheved by \fB::msgcat::mcpreferences\fR {*}[\fB::msgcat::mcutil getpreferences\fR \fInewLocale\fR].
.PP
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

.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.

.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:

.CS
::msgcat::mcpreferences fr en {}
.CE
.RE
.PP
.VS "TIP 499"
.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.

.PP
.RS
The subcommand \fBget\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.

.RE


.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

.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.


.VE "TIP 412"
.RE

.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.

.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.

.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.

.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.

.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.

.RE

.TP
\fB::msgcat::mcforgetpackage\fR
.
The calling package clears all its state within the \fBmsgcat\fR package including all settings and translations.

.VE "TIP 412"
.PP


.VS "TIP 499"
.TP
\fB::msgcat::mcutil getpreferences\fR \fIlocale\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:

.CS
% concat [lrange [msgcat::mcutil getpreferences fr_CH] 0 end-1] [msgcat::mcutil getpreferences de_CH]
fr_ch fr de_ch de {}
.CE

.TP
\fB::msgcat::mcutil getsystemlocale\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







|

|
|
|
>


|
>
|

|
>







|

|
|



|
>

|
>
>



|




|


|
|
|


|
>

















>



|
|


|
>
|
>

>
|

|
>












>










|
>



|
>





|

|
|
|
>


|

<
<
|
>

>
>


<


|
|
>










|
>
>


>







>











>


>





>


>







>
















|
>

>



|
>


>
>


|

|
>
|
>




>



|
>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232


233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
.\" COMMAND: mcc
.TP
\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.
.RE
.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).
.\" COMMAND: mcexists
.TP
\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.
.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).
.PP
.VE "TIP 412"
.VS "TIP 490"
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"
.\" COMMAND: mcpackagenamespaceget
.TP
\fB::msgcat::mcpackagenamespaceget\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:
.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.
.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.
.PP
The same result may be achieved by \fB::msgcat::mcpreferences\fR
{*}[\fB::msgcat::mcutil getpreferences\fI newLocale\fR].
.PP
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.
.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:
.CS
::msgcat::mcpreferences fr en {}
.CE
.RE
.PP
.\" COMMAND: mcloadedlocales
.TP
\fB::msgcat::mcloadedlocales subcommand\fR ?\fIlocale\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 \fBloaded\fR returns the list of currently loaded locales.
.PP


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 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.
.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.
.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.
.VE "TIP 412"
.PP
.\" COMMAND: mcutil
.\" METHOD: getpreferences
.VS "TIP 499"
.TP
\fB::msgcat::mcutil getpreferences\fI locale\fR
.
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.
.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
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
.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"
is transformed to the locale as "lang_country_script" (Example:
sr-Latn-CS -> sr_cs_latin). For Windows XP, the language id is
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







|







381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
.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"
is transformed to the locale as "lang_country_script" (Example:
sr-Latn-CS -> sr_cs_latin). For Windows XP, the language id is
transformed analogously (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
.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).


.PP
This action is controled by the following ensemble:


.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).

.PP
.RS
This command may cause the load of locales.
.RE

.TP
\fB::msgcat::mcpackagelocale get\fR
.
Return the package private locale or the global locale, if no package private locale is set.


.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).

.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.
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.
.VE "TIP 499"
.RE
.PP

.TP
\fB::msgcat::mcpackagelocale loaded\fR
.
Return the list of locales loaded for this package.

.TP
\fB::msgcat::mcpackagelocale isset\fR
.
Returns true, if a package private locale is set.

.TP
\fB::msgcat::mcpackagelocale unset\fR
.
Unset the package private locale and use the globale locale.
Load and remove locales to adjust the list of loaded locales for the
package to the global loaded locales list.

.TP
\fB::msgcat::mcpackagelocale present\fR \fIlocale\fR
.
Returns true, if the given locale is loaded for the package.

.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:



.TP
\fB::msgcat::mcpackageconfig get\fR \fIoption\fR
.
Return the current value of the given \fIoption\fR.
This call returns an error if the option is not set for the package.

.TP
\fB::msgcat::mcpackageconfig isset\fR \fIoption\fR
.
Returns 1, if the given \fIoption\fR is set for the package, 0 otherwise.

.TP
\fB::msgcat::mcpackageconfig set\fR \fIoption\fR \fIvalue\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.


.TP
\fB::msgcat::mcpackageconfig unset\fR \fIoption\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.


.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).


.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.

.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).


.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.

.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.


.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).

.PP
.RS
The called procedure must return the formatted message which will finally be returned by msgcat::mc.

.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.


.PP
See section \fBcallback invocation\fR below.
The appended arguments are identical to \fB::msgcat::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.

.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:



.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.

.CS
namespace eval ::N3Class {
    mcload $dir/msgs
    oo::class create C1
    oo::define C1 method m1 {
        puts [mc Hi!]
    }







|
>
>


>
>




|
>
|
>




>



|
>
>



|
|
|
>



|
|






>




>




>



|


>

|


>









|
>
>
>

|



>

|


>

|



|
>
>

|










|
>
>


|
>
>






|
>


|
>
>




|
>




|
>
>









|
>


|
>

|
>
>


|












|
>
|
>






|
>
>
>















|
>







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
.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).
.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).
.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.
.\" 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).
.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.
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.
.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 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\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:
.\" COMMAND: mcpackageconfig
.\" METHOD: get
.TP
\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\fI option\fR
.
Returns 1, if the given \fIoption\fR is set for the package, 0 otherwise.
.\" METHOD: set
.TP
\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.
.\" METHOD: unset
.TP
\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.
.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).
.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.
.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).
.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.
.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.
.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 (\fBmsgcat::mcunknown\fR).
.PP
.RS
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 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 \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.
.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:
.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.
.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
        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:
.CS
namespace eval gui {
    msgcat::mcpackageconfig changecmd updateGUI

    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:

.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.

Here are some sketches of the implementation:
.PP
First, a package locale is initialized and the generic unknown function is desactivated:

.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
.CE
\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:

.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

.\" Local Variables:
.\" mode: nroff
.\" End:







|
|




|








|
>














|
>


|
>






|

|
>





|
>


















|
>



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
        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:
.CS
namespace eval gui {
    msgcat::mcpackageconfig changecmd updateGUI

    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
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.
Here are some sketches of the implementation:
.PP
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
.CE
\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:
.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
.\" 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
.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

\fBmy\fI methodName\fR ?\fIarg ...\fR?
\fBmyclass\fI methodName\fR ?\fIarg ...\fR?
.fi
.BE
.SH DESCRIPTION
.PP







|







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 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
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.
.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







|
|
|







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.
.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
.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?
.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.

.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.

.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.







|









>
















>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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?
.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
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.

.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.

.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.

.TP
\fBnamespace ensemble\fR \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.

.TP
\fBnamespace eval\fR \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

.TP
\fBnamespace exists\fR \fInamespace\fR
.
Returns \fB1\fR if \fInamespace\fR is a valid namespace in the current
context, returns \fB0\fR otherwise.

.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







>









>












>

|




>

|














>

|



>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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 \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 \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 \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
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.

.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







>







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
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.

.TP
\fBnamespace import \fR?\fB\-force\fR? ?\fIpattern\fR \fIpattern ...\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.







|
>

|







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 undoes the action of a \fBnamespace import\fR command.
.\" METHOD: import
.TP
\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
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

.TP
\fBnamespace inscope\fR \fInamespace\fR \fIscript\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







>

|







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 \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
.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

.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.

.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.

.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.

.TP
\fBnamespace qualifiers\fR \fIstring\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,
the names of currently defined namespaces.

.TP
\fBnamespace tail\fR \fIstring\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.

.TP
\fBnamespace upvar\fR \fInamespace\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.

.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.

.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,







>















>







>









>

|







<
|

>

|









>

|









>













>







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289

290
291
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\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.

It does not check whether the namespace names are, in fact,
the names of currently defined namespaces.
.\" METHOD: tail
.TP
\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\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,
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
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}
.CE
.PP
returns \fB::traceLevel\fR.
On the other hand, the command,
.PP
.CS
\fBnamespace eval\fR Foo {\fBnamespace which\fR \-variable traceLevel}
.CE
.PP
returns \fB::Foo::traceLevel\fR.
.PP
As mentioned above,
namespace names are looked up differently
than the names of variables and commands.







|






|







541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
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}
.CE
.PP
returns \fB::traceLevel\fR.
On the other hand, the command,
.PP
.CS
\fBnamespace eval\fR Foo {\fBnamespace which\fR -variable traceLevel}
.CE
.PP
returns \fB::Foo::traceLevel\fR.
.PP
As mentioned above,
namespace names are looked up differently
than the names of variables and commands.
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
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::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
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







|
















|







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
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::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
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
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
.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::*







|







636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
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
.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
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:

.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.

.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.

.TP
\fBnamespace ensemble exists\fR \fIcommand\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







>











>







>

|







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
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\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
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:

.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.

.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.

.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.

.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.

.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:

.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:

.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







>















>


>




>







>











>














>











>







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
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
.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

\fBnext\fR ?\fIarg ...\fR?
\fBnextto\fI class\fR ?\fIarg ...\fR?
.fi
.BE

.SH DESCRIPTION







|







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 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
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.
.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.







|
|
|
|







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.
.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
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
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







|







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 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
.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

\fBoo::object\fI method \fR?\fIarg ...\fR?
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
.fi







|







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 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
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:

.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:

.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.

.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.

.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.

.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.

.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







>










>






>














>








>





>







44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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.
.\" 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
.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
\fBopen \fIfileName\fR
.br
\fBopen \fIfileName access\fR
.br
\fBopen \fIfileName access permissions\fR

.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
.
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
.
Open the file for both reading and writing; the file must
already exist.
.TP 15
\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
.
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
.
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
.
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.
One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR.
.TP 15
\fBRDONLY\fR
.
Open the file for reading only.
.TP 15
\fBWRONLY\fR
.
Open the file for writing only.
.TP 15
\fBRDWR\fR
.
Open the file for both reading and writing.
.TP 15
\fBAPPEND\fR
.
Set the file pointer to the end of the file prior to each write.
.TP 15
\fBBINARY\fR
.
Configure the opened channel with the \fB\-translation binary\fR option.
.TP 15
\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
.
If \fBCREAT\fR is also specified, an error is returned if the
file already exists.
.TP 15
\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
.
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
.
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.























.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







|

<

<

>














<
|
<


<
|
<


<
|
<


<
|
<


<
|
<



<
|
<











|

<
|
<

<
|
<

<
|
<

<
|
<

<
|
<

<
|
<


<
|
<


<
|
<


<
|
<







<
|
<






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







8
9
10
11
12
13
14
15
16

17

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34

35
36

37

38
39

40

41
42

43

44
45

46

47
48
49

50

51
52
53
54
55
56
57
58
59
60
61
62
63

64

65

66

67

68

69

70

71

72

73

74

75
76

77

78
79

80

81
82

83

84
85
86
87
88
89
90

91

92
93
94
95
96
97
98
99
100
101
102
103
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
.nf
\fBopen \fIfileName\fR

\fBopen \fIfileName access\fR

\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:

.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.

.IP \fBr+\fR

Open the file for both reading and writing; the file must
already exist.

.IP \fBw\fR

Open the file for writing only.  Truncate it if it exists.  If it does not
exist, create a new file.

.IP \fBw+\fR

Open the file for reading and writing.  Truncate it if it exists.
If it does not exist, create a new file.

.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.

.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, most of which have the standard POSIX meanings.
One of the flags must be either \fBRDONLY\fR, \fBWRONLY\fR or \fBRDWR\fR.

.IP \fBRDONLY\fR

Open the file for reading only.

.IP \fBWRONLY\fR

Open the file for writing only.

.IP \fBRDWR\fR

Open the file for both reading and writing.

.IP \fBAPPEND\fR

Set the file pointer to the end of the file prior to each write.

.IP \fBBINARY\fR

Configure the opened channel with the \fB\-translation binary\fR option.

.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).

.IP \fBEXCL\fR

If \fBCREAT\fR is also specified, an error is returned if the
file already exists.

.IP \fBNOCTTY\fR

If the file is a terminal device, this flag prevents the file from
becoming the controlling terminal of the process.

.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.

.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
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):

.TP
\fB\-mode\fR \fIbaud\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.

.TP
\fB\-handshake\fR \fItype\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

.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.

.TP
\fB\-timeout\fR \fImsec\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.

.TP
\fB\-ttycontrol\fR \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.

.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.

.TP
\fB\-xchar\fR \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.

.TP
\fB\-closemode\fR \fIcloseMode\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
.
indicates that a system default operation should be used; all serial channels
default to this.
.TP
\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
.
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"

.TP
\fB\-inputmode\fR \fIinputMode\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
.
indicates that normal line-oriented input should be used, with standard
terminal editing capabilities enabled.
.TP
\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
.
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)
.
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

.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"

.TP
\fB\-pollinterval\fR \fImsec\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).

.TP
\fB\-sysbuffer\fR \fIinSize\fR
.TP
\fB\-sysbuffer\fR \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.

.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)
\fBTransmitted Data:\fR Outgoing serial data.
.IP \fBRXD\fR(input)
\fBReceived Data:\fRIncoming serial data.
.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)
\fBClear To Send:\fR The complement to RTS. Indicates that the modem is
ready to receive data.
.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)
\fBData Set Ready:\fR The complement to DTR. Tells the workstation that the
modem is ready to establish a link.
.IP \fBDCD\fR(input)
\fBData Carrier Detect:\fR This line becomes active when a modem detects a
.QW Carrier
signal.
.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
.
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.
.TP 10
\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
.
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
.
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.
.TP 10
\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.
.TP 10
\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.







>

|















>

|
















>






>

|








>

|











>









>

|





>

|






<
|
<


<
|
<



<
|
<




>

|







<
|
<


<
|
<



<
|
<



<
|
<







>







>

|







>

|

|






>


















|

|

|



|


|



|


|



|

















<
|
<

|
|
<
|
<


<
|
<




<
|
<

|
|
<
|
<

|
|
<
|
<







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257

258

259
260

261

262
263
264

265

266
267
268
269
270
271
272
273
274
275
276
277
278
279

280

281
282

283

284
285
286

287

288
289
290

291

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\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\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\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\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\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\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

.IP \fBdefault\fR

indicates that a system default operation should be used; all serial channels
default to this.

.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.

.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\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

.IP \fBnormal\fR

indicates that normal line-oriented input should be used, with standard
terminal editing capabilities enabled.

.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.

.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.

.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\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\fI inSize\fR
.TP
\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)"
\fBTransmitted Data:\fR Outgoing serial data.
.IP "\fBRXD\fR (input)"
\fBReceived Data:\fRIncoming serial data.
.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)"
\fBClear To Send:\fR The complement to RTS. Indicates that the modem is
ready to receive data.
.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)"
\fBData Set Ready:\fR The complement to DTR. Tells the workstation that the
modem is ready to establish a link.
.IP "\fBDCD\fR (input)"
\fBData Carrier Detect:\fR This line becomes active when a modem detects a
.QW Carrier
signal.
.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.

.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.

.IP \fBTXFULL\fR

Windows output buffer overrun. Complement to RXOVER. This error should
practically not happen, because Tcl cares about the output buffer status.

.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.

.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.

.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.

.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
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.






.RE
.TP
\fBUnix\fR\0\0\0\0\0\0\0
.
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







>
>
>
>
>
>


|







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
.
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
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:

.TP
\fB\-inputmode\fR \fIinputMode\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
.
indicates that normal line-oriented input should be used, with standard
console editing capabilities enabled.
.TP
\fBpassword\fR
.
indicates that non-echoing input should be used, with standard console
editing capabilitied enabled but no writing of typed characters to the
terminal (except for newlines).
.TP
\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

.TP
\fB\-winsize\fR
.
This option is query only.
It retrieves a two-element list with the 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"













.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
.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







>

|





<
|
<


<
|
<

|

<
|
<













>




|






>
>
>
>
>
>
>
>
>
>
>
>
>










>
>
>
>
>
>
>
>
>
>
>
>







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\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

.IP \fBnormal\fR

indicates that normal line-oriented input should be used, with standard
console editing capabilities enabled.

.IP \fBpassword\fR

indicates that non-echoing input should be used, with standard console
editing capabilities enabled but no writing of typed characters to the
terminal (except for newlines).

.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 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
.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 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?







|







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\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
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:

.TP
\fBpackage files\fR \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.

.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.

.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







>

|





>






>







39
40
41
42
43
44
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 \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
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.

.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.

.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.

.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.

.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.







>








>





>













>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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
.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.

.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







>







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
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.

.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.

.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.

.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
.
This form is called
.QW min-bounded .
.TP
min-
.
This form is called
.QW min-unbound .
.TP
min-max
.
This form is called
.QW bounded .
.RE
.RS
.PP
where
.QW min
and
.QW max
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







>






>






>







<
|
<


<
|
<


<
|
<


<
<


|

|



<
<







182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

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

.IP \fImin\fR

This form is called
.QW min-bounded .

.IP \fImin\fB\-\fR

This form is called
.QW min-unbound .

.IP \fImin\fB\-\fImax\fR

This form is called
.QW bounded .


.PP
where
.QW \fImin\fR
and
.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:


.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
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

.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







>


>







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
'\"
'\" Copyright (c) 1998-2000 by 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:

.TP
\fB\-name \fIpackageName\fR

This parameter specifies the name of the package.  It is required.

.TP
\fB\-version \fIpackageVersion\fR

This parameter specifies the version of the package.  It is required.

.TP
\fB\-load \fIfilespec\fR

This parameter specifies a binary 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.

.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"

|











<






<


>


>

>


>

>


>
|






>


>







1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19

20
21
22
23
24
25
26
27
28
29
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 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 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
.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.







<







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
# 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:







<








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
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:

.TP 15
\fB\-direct\fR

The generated index will implement direct loading of the package
upon \fBpackage require\fR.  This is the default.

.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.

.TP 15
\fB\-load \fIpkgPat\fR

The index process will pre-load 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.

.TP 15
\fB\-verbose\fR

Generate output during the indexing process.  Output is via
the \fBtclLog\fR procedure, which by default prints to stderr.

.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.







>


>


>


>




>


>
|




>


>


>


>







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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 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
.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







|







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?

\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
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

.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.

.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.

.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







>









>







>







39
40
41
42
43
44
45
46
47
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
.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







|







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?

\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
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

.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.

.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.

.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:







>


>


>


>


>


>








37
38
39
40
41
42
43
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
.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 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:

.TP
\fB::tcl::prefix all\fR \fItable string\fR
.
Returns a list of all elements in \fItable\fR that begin with the prefix
\fIstring\fR.

.TP
\fB::tcl::prefix longest\fR \fItable string\fR
.
Returns the longest common prefix of all elements in \fItable\fR that
begin with the prefix \fIstring\fR.

.TP
\fB::tcl::prefix match\fR ?\fIoptions\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.)
.RS

.TP
\fB\-exact\fR\0
.
Accept only exact matches.

.TP
\fB\-message\0\fIstring\fR
.
Use \fIstring\fR in the error message at a mismatch. Default is
.QW option .

.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
       "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
     \fI\(-> bad option "a": must be apa, bepa, or cepa\fR
\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}
foreach {arg val} $args {
    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] {







|
|







>

|



>

|



>










>

|


>





>














|














|

|










|

|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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\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\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\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
.
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.)
.RS
.\" OPTION: -exact
.TP
\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
       "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
     \fI\(-> bad option "a": must be apa, bepa, or cepa\fR
\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}
foreach {arg val} $args {
    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
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.
.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.







|
|
|
|







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.
.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.

14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36

37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
\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:

.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.

.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.

.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.

.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
.
is a standard Tcl return code, i.e., \fB0\fR for TCL_OK and \fB1\fR
for TCL_ERROR,
.TP
\fImsg\fR\0
.
is the human-readable error message,
.TP
\fIerrorCode\fR\0
.
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:

.TP
\fB\-wait\fR\0
.
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.

.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"







>










>






>







>












|




|



|









>

|






>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
\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
.
is a standard Tcl return code, i.e., \fB0\fR for TCL_OK and \fB1\fR
for TCL_ERROR,
.TP
\fImsg\fR
.
is the human-readable error message,
.TP
\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
.
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.

58
59
60
61
62
63
64





65
66
67
68
69
70
71
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!"







>
>
>
>
>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
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 "ENCODING ERRORS"
.PP
Encoding errors may exist, if the encoding profile \fBstrict\fR is used.
\fBputs\fR writes out data until an encoding error occurs and fails with
POSIX error code \fBEILSEQ\fR.
.SH EXAMPLES
.PP
Write a short message to the console (or wherever \fBstdout\fR is
directed):
.PP
.CS
\fBputs\fR "Hello, World!"

Changes to doc/re_syntax.n.

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140


141
142
143
144













145
146
147
148
149
150
151
.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
.
a sequence of 0 or more matches of the atom
.TP
\fB+\fR
.
a sequence of 1 or more matches of the atom
.TP
\fB?\fR
.
a sequence of 0 or 1 matches of the atom
.TP
\fB{\fIm\fB}\fR
.
a sequence of exactly \fIm\fR matches of the atom
.TP
\fB{\fIm\fB,}\fR
.
a sequence of \fIm\fR or more matches of the atom
.TP
\fB{\fIm\fB,\fIn\fB}\fR
.
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
as previous, but does no reporting (a
.QW non-capturing
set of parentheses)
.IP \fB()\fR
matches an empty string, noted for possible reporting
.IP \fB(?:)\fR
matches an empty string, without reporting
.IP \fB[\fIchars\fB]\fR
a \fIbracket expression\fR, matching any one of the \fIchars\fR (see
\fBBRACKET EXPRESSIONS\fR for more detail)
.IP \fB.\fR
matches any single character
.IP \fB\e\fIk\fR
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
where \fIc\fR is alphanumeric (possibly followed by other characters),
an \fIescape\fR (AREs only), see \fBESCAPES\fR below
.IP \fB{\fR
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
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


.TP
\fB$\fR
.
matches at the end of a line













.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







<
|
<

<
|
<

<
|
<

<
|
<

<
|
<

<
|
<



















|



|

|

|


|

|



|


|




|












|
>
>



|
>
>
>
>
>
>
>
>
>
>
>
>
>







53
54
55
56
57
58
59

60

61

62

63

64

65

66

67

68

69

70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
.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

.IP \fB*\fR 6

a sequence of 0 or more matches of the atom

.IP \fB+\fR 6

a sequence of 1 or more matches of the atom

.IP \fB?\fR 6

a sequence of 0 or 1 matches of the atom

.IP \fB{\fIm\fB}\fR 6

a sequence of exactly \fIm\fR matches of the atom

.IP \fB{\fIm\fB,}\fR 6

a sequence of \fIm\fR or more matches of the atom

.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 6
as previous, but does no reporting (a
.QW non-capturing
set of parentheses)
.IP \fB()\fR 6
matches an empty string, noted for possible reporting
.IP \fB(?:)\fR 6
matches an empty string, without reporting
.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 6
matches any single character
.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 6
where \fIc\fR is alphanumeric (possibly followed by other characters),
an \fIescape\fR (AREs only), see \fBESCAPES\fR below
.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 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 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 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
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
equivalence class, then
.QW \fB[[=o=]]\fR ,
.QW \fB[[=\[^o]=]]\fR ,
and
.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
.
alert (bell) character, as in C
.TP
\fB\eb\fR
.
backspace, as in C
.TP
\fB\eB\fR
.
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
.
(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
.
the character whose collating-sequence name is
.QW \fBESC\fR ,
or failing that, the character with octal value 033
.TP
\fB\ef\fR
.
formfeed, as in C
.TP
\fB\en\fR
.
newline, as in C
.TP
\fB\er\fR
.
carriage return, as in C
.TP
\fB\et\fR
.
horizontal tab, as in C
.TP
\fB\eu\fIwxyz\fR
.
(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
.
(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
hexadecimal digits are reached, or an overflow would occur in the maximum
value of \fBU+\fI10ffff\fR.
.TP
\fB\ev\fR
.
vertical tab, as in C
.TP
\fB\ex\fIhh\fR
.
(where \fIhh\fR is one or two hexadecimal digits) the character
whose hexadecimal value is \fB0x\fIhh\fR.
.TP
\fB\e0\fR
.
the character whose value is \fB0\fR
.TP
\fB\e\fIxyz\fR
.
(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
.
(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 ,







|


|

|




















<
|
<

<
|
<

<
|
<


<
|
<


<
|
<



<
|
<

<
|
<

<
|
<

<
|
<

<
|
<


<
|
<


|


<
|
<

<
|
<


<
|
<

<
|
<




<
|
<







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
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
equivalence class, then
.QW \fB[[=o=]]\fR ,
.QW \fB[[=\(^o=]]\fR ,
and
.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

.IP \fB\ea\fR 5

alert (bell) character, as in C

.IP \fB\eb\fR 5

backspace, as in C

.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

.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

.IP \fB\ee\fR 5

the character whose collating-sequence name is
.QW \fBESC\fR ,
or failing that, the character with octal value 033

.IP \fB\ef\fR 5

formfeed, as in C

.IP \fB\en\fR 5

newline, as in C

.IP \fB\er\fR 5

carriage return, as in C

.IP \fB\et\fR 5

horizontal tab, as in C

.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

.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 maximum of eight
hexadecimal digits are reached, or an overflow would occur in the maximum
value of \fBU+\fI10ffff\fR.

.IP \fB\ev\fR 5

vertical tab, as in C

.IP \fB\ex\fIhh\fR 5

(where \fIhh\fR is one or two hexadecimal digits) the character
whose hexadecimal value is \fB0x\fIhh\fR.

.IP \fB\e0\fR 5

the character whose value is \fB0\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.

.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
.TP
\fB\es\fR
.
\fB[[:space:]]\fR
.TP
\fB\ew\fR
.
\fB[[:alnum:]_]\fR (note underscore)

.TP
\fB\eD\fR
.
\fB[^[:digit:]]\fR
.TP
\fB\eS\fR
.
\fB[^[:space:]]\fR
.TP
\fB\eW\fR
.
\fB[^[:alnum:]_]\fR (note underscore)

.RE
.PP
Within bracket expressions,
.QW \fB\ed\fR ,
.QW \fB\es\fR ,
and
.QW \fB\ew\fR \&







|
>











|
>







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
.TP
\fB\es\fR
.
\fB[[:space:]]\fR
.TP
\fB\ew\fR
.
\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:]_\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
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
.
matches only at the beginning of the string (see \fBMATCHING\fR,
below, for how this differs from
.QW \fB^\fR )
.TP
\fB\em\fR
.
matches only at the beginning of a word
.TP
\fB\eM\fR
.
matches only at the end of a word
.TP
\fB\ey\fR
.
matches only at the beginning or end of a word
.TP
\fB\eY\fR
.
matches only at a point that is not the beginning or end of a word
.TP
\fB\eZ\fR
.
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
.
(where \fIm\fR is a nonzero digit) a \fIback reference\fR, see below
.TP
\fB\e\fImnn\fR
.
(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







<
|
<



<
|
<

<
|
<

<
|
<

<
|
<

<
|
<



<
|
<

<
|
<







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
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

.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 )

.IP \fB\em\fR 6

matches only at the beginning of a word

.IP \fB\eM\fR 6

matches only at the end of a word

.IP \fB\ey\fR 6

matches only at the beginning or end of a word

.IP \fB\eY\fR 6

matches only at a point that is not the beginning or end of a word

.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 )

.IP \fB\e\fIm\fR 6

(where \fIm\fR is a nonzero digit) a \fIback reference\fR, see below

.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.

46
47
48
49
50
51
52









































































53
54
55
56
57
58
59
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:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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 "ENCODING ERRORS"
.PP
Encoding errors may exist, if the encoding profile \fBstrict\fR is used.
Encoding errors are special, as an eventual introspection or  recovery is
possible by changing to an encoding (or encoding profile), which accepts
the data.
An encoding error is reported by the POSIX error code \fBEILSEQ\fR.
.PP
In blocking mode, the error is directly thrown, even, if there is a
leading decodable data portion.
The file pointer is advanced just before the encoding error.
An eventual well decoded data chunk before the encoding error is returned
in the error option dictionary key \fB\-data\fR.
The value of the key contains the empty string, if the error arises at the
first data position.
.PP
In non blocking mode, first, any data without encoding error is returned
(without error state).
In the next call, no data is returned and the \fBEILSEQ\fR error state is set.
The key \fB\-data\fR is not present.
.PP
Here is an example with an encoding error in UTF-8 encoding, which is then
introspected by a switch to the binary encoding. The test file contains a not
continued multi-byte sequence at position 1 (\fBA \\xC3 B\fR):
.PP
File creation for examples
.
.CS
% set f [open test_A_195_B.txt wb]; puts -nonewline $f A\\xC3B; close $f
.CE
Blocking example
.
.CS
% set f [open test_A_195_B.txt r]
file35a65a0
% fconfigure $f -encoding utf-8 -profile strict -blocking 1
% catch {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
% tell $f
1
% fconfigure $f -encoding binary -profile strict
% read $f
ÃB
% close $f
.CE
The already 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 \fBread\fR command.
.PP
Non blocking example
.
.CS
% set f [open test_A_195_B.txt r]
file35a65a0
% fconfigure $f -encoding utf-8 -profile strict -blocking 0
% read $f
A
% tell $f
1
% catch {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
.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:
79
80
81
82
83
84
85
86

87
88
89
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

'\"Local Variables:
'\"mode: nroff
'\"End:







|
>



152
153
154
155
156
157
158
159
160
161
162
163
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
'\"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
'\"
'\" Copyright (c) 2006 Andreas Kupries <[email protected]>
'\"
'\" 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


\fBcmdPrefix \fIoption\fR ?\fIarg arg ...\fR?











.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"

.TP
\fIcmdPrefix \fBinitialize \fIchannelId mode\fR
.
An invocation of this subcommand will be the first call the
\fIcmdPrefix\fR will receive for the specified new \fIchannelId\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.













>
>
|
>
>
>
>
>
>
>
>
>
>
>

















>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
'\"
'\" Copyright (c) 2006 Andreas Kupries <[email protected]>
'\"
'\" 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

\fIcmdPrefix \fBblocking\fI channelId mode\fR
\fIcmdPrefix \fBcget\fI channelId option\fR
\fIcmdPrefix \fBcgetall\fI channelId\fR
\fIcmdPrefix \fBconfigure\fI channelId option value\fR
\fIcmdPrefix \fBfinalize\fI channelId\fR
\fIcmdPrefix \fBinitialize\fI channelId mode\fR
\fIcmdPrefix \fBread\fI channelId count\fR
\fIcmdPrefix \fBseek\fI channelId offset base\fR
\fIcmdPrefix \fBwatch\fI channelId eventspec\fR
\fIcmdPrefix \fBwrite\fI channelId 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
.
An invocation of this subcommand will be the first call the
\fIcmdPrefix\fR will receive for the specified new \fIchannelId\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.
49
50
51
52
53
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
(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.
.PP
The subcommand must throw an error if the chosen mode is not
supported by the \fIcmdPrefix\fR.
.RE

.TP
\fIcmdPrefix \fBfinalize \fIchannelId\fR
.
An invocation of this subcommand will be the last call the
\fIcmdPrefix\fR will receive for the specified \fIchannelId\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







|
|




>







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
(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 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
.
An invocation of this subcommand will be the last call the
\fIcmdPrefix\fR will receive for the specified \fIchannelId\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
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
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

.TP
\fIcmdPrefix \fBwatch \fIchannelId eventspec\fR
.
This subcommand notifies the \fIcmdPrefix\fR that the specified
\fIchannelId\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"

.TP
\fIcmdPrefix \fBread \fIchannelId 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
requested. If the subcommand is not supported then it is not possible to read
from the channel handled by the command.







>




















>







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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
.
This subcommand notifies the \fIcmdPrefix\fR that the specified
\fIchannelId\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
.
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
requested. If the subcommand is not supported then it is not possible to read
from the channel handled by the command.
153
154
155
156
157
158
159

160
161
162
163
164
165
166
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

.TP
\fIcmdPrefix \fBwrite \fIchannelId 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
characters. Any type of transformation (EOL, encoding) configured for
the channel has already been applied at this point. If this subcommand







>







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
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
.
This \fIoptional\fR subcommand is called when the user writes data to
the channel \fIchannelId\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
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277

278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
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

.TP
\fIcmdPrefix \fBseek \fIchannelId 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
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
.
Seeking is relative to the beginning of the channel.
.TP 10
\fBcurrent\fR
.
Seeking is relative to the current seek position.
.TP 10
\fBend\fR
.
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

.TP
\fIcmdPrefix \fBconfigure \fIchannelId 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
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

.TP
\fIcmdPrefix \fBcget \fIchannelId 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
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

.TP
\fIcmdPrefix \fBcgetall \fIchannelId\fR
.
This \fIoptional\fR subcommand is used for reading all type-specific options
of channel \fIchannelId\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

.TP
\fIcmdPrefix \fBblocking \fIchannelId 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
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














.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







>











<
|
<

<
|
<

<
|
<




















>



















>















>
















>
















>
>
>
>
>
>
>
>
>
>
>
>
>
>







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

247

248

249

250

251

252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
.
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
the channel.
.RS
.PP
The \fIbase\fR argument is the same as the equivalent argument of the
builtin \fBchan seek\fR, namely:

.IP \fBstart\fR 10

Seeking is relative to the beginning of the channel.

.IP \fBcurrent\fR 10

Seeking is relative to the current seek position.

.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
.
This \fIoptional\fR subcommand is for setting the type-specific options of
channel \fIchannelId\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
.
This \fIoptional\fR subcommand is used when reading a single type-specific
option of channel \fIchannelId\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
.
This \fIoptional\fR subcommand is used for reading all type-specific options
of channel \fIchannelId\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
.
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
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 channelId length\fR
.
This \fIoptional\fR subcommand handles changing the length of the
underlying data stream for the channel \fIchannelId\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
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:

.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.

.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).

.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.

.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).

.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).

.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).

.TP 15
\fB\-nocase\fR
.
Causes upper-case characters in \fIstring\fR to be treated as
lower case during the matching process.

.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.

.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

.TP 15
\fB\-start\fR \fIindex\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.

.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







>








>






>









>


















>










>













>





>







>



















>

|












>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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\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
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
.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
.CE
.PP
This counts the number of octal digits in a string:
.PP
.CS
\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
.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:







|







|





|







|








182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
.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
.CE
.PP
This counts the number of octal digits in a string:
.PP
.CS
\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
.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
.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
\fBpackage require registry 1.3\fR
.sp
\fBregistry \fR?\fI\-mode\fR? \fIoption\fR \fIkeyName\fR ?\fIarg arg ...\fR?

.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







|

|
|
>







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
.nf
\fBpackage require registry 1.3\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
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:

.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.







>







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
    Environment
} "\e\e"]
set curPath [\fBregistry get\fR $regPath "Path"]
\fBregistry set\fR $regPath "Path" "$curPath;$addPath"
\fBregistry broadcast\fR "Environment"
.CE
.RE

.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.

.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.

.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.

.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.

.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.

.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
.
The registry value contains arbitrary binary data.  The data is represented
exactly in Tcl, including any embedded nulls.
.TP
\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
.
The registry value contains a null-terminated string.  The data is
represented in Tcl as a string.
.TP
\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
.
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
.
The registry value contains a big-endian 32-bit number.  The data is
represented in Tcl as a decimal string.
.TP
\fBlink\fR
.
The registry value contains a symbolic link.  The data is represented
exactly in Tcl, including any embedded nulls.
.TP
\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
.
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.







>









>







>








>










>






>

















<
|
<


<
|
<



<
|
<


<
|
<





<
|
<


<
|
<


<
|
<


<
|
<


<
|
<







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

147

148
149

150

151
152
153

154

155
156

157

158
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:

.IP \fBbinary\fR

The registry value contains arbitrary binary data.  The data is represented
exactly in Tcl, including any embedded nulls.

.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.

.IP \fBsz\fR

The registry value contains a null-terminated string.  The data is
represented in Tcl as a string.

.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.

.IP \fBdword\fR

The registry value contains a little-endian 32-bit number.  The data is
represented in Tcl as a decimal string.

.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.

.IP \fBlink\fR

The registry value contains a symbolic link.  The data is represented
exactly in Tcl, including any embedded nulls.

.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.

.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
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:

.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.

.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
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

.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).

.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).

.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).

.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).

.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.

.TP
\fB\-start\fR \fIindex\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.

.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







>













>













|













>






>

















>










>













>






>

|










>







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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
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\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
        return " "
    }
    # convert hex to a char
    scan $h %x charNumber
    format %c $charNumber
}}}]
.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:







>
>
>
>
>
>
>
>
>








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
.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

\fBreturn \fR?\fIresult\fR?
.sp
\fBreturn \fR?\fB\-code \fIcode\fR? ?\fIresult\fR?
.sp
\fBreturn \fR?\fIoption value \fR...? ?\fIresult\fR?

.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.







>

<

<

>







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?

\fBreturn \fR?\fB\-code \fIcode\fR? ?\fIresult\fR?

\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
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
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).







|







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\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).
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
116
117
118
119

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137

138
139

140
141
142

143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
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:

.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.

.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).

.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

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).

.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.

.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"







>












>


















>


>


|
>











>












>







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
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
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
'\"
'\" 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

\fB::safe::interpCreate\fR ?\fIchild\fR? ?\fIoptions...\fR?
.sp
\fB::safe::interpInit\fR \fIchild\fR ?\fIoptions...\fR?
.sp
\fB::safe::interpConfigure\fR \fIchild\fR ?\fIoptions...\fR?
.sp
\fB::safe::interpDelete\fR \fIchild\fR
.sp
\fB::safe::interpAddToAccessPath\fR \fIchild\fR \fIdirectory\fR
.sp
\fB::safe::interpFindInAccessPath\fR \fIchild\fR \fIdirectory\fR
.sp

\fB::safe::setLogCmd\fR ?\fIcmd arg...\fR?

.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?

.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













>

<
|
<
|
<
|
<
|
<
|
<
>

>

|
|
>
|
>
>
|
|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

16

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?

\fB::safe::interpInit\fI child\fR ?\fIoptions...\fR?

\fB::safe::interpConfigure\fI child\fR ?\fIoptions...\fR?

\fB::safe::interpDelete\fI child\fR

\fB::safe::interpAddToAccessPath\fI child directory\fR

\fB::safe::interpFindInAccessPath\fI child directory\fR

\fB::safe::setSyncMode\fR ?\fInewValue\fR?
\fB::safe::setLogCmd\fR ?\fIcmd arg...\fR?
.fi
.SS OPTIONS
.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
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:

.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

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.


.TP
\fB::safe::interpInit\fR \fIchild\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.

.TP
\fB::safe::interpConfigure\fR \fIchild\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]

# 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
.CE
.RE

.TP
\fB::safe::interpDelete\fR \fIchild\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.

.TP
\fB::safe::interpFindInAccessPath\fR \fIchild\fR \fIdirectory\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

.TP
\fB::safe::interpAddToAccessPath\fR \fIchild\fR \fIdirectory\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

.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.







>


>







|
>





>
>

|
>





>

|
>


















|



|


>

|
>





>

|
>











>

|
>













>

>
>
>
>
>
>
>
>
>
>
>

>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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.
.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\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\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]

# 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
.CE
.RE
.\" COMMAND: interpDelete
.TP
\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\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\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
.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.

.TP
\fB\-accessPath\fR \fIdirectoryList\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.

.TP









\fB\-statics\fR \fIboolean\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.

.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.

.TP
\fB\-nested\fR \fIboolean\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.

.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.

.TP
\fB\-deleteHook\fR \fIscript\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

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

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?

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
subcommands. For more details on what these subcommands do see the manual
page for the \fBfile\fR command.
.TP
\fBencoding\fR ?\fIsubCmd 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







>

|
>







>

>
>
>
>
>
>
>
>
>
|
>




>


>



>

|
>





>


>



>

|
>










|
>










|
>







|
>






|
>






>







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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\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\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\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\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\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\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 ?\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
subcommands. For more details on what these subcommands do see the manual
page for the \fBfile\fR command.
.TP
\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
.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,

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







|
>







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 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
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 "SEE ALSO"
interp(n), library(n), load(n), package(n), source(n), unknown(n)

.SH KEYWORDS
alias, auto\-loading, auto_mkindex, load, parent interpreter, safe
interpreter, child interpreter, source
'\" Local Variables:
'\" mode: nroff
'\" End:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>

|




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 8.7, 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/tcl8.6
    /usr/local/TclHome/lib/tcl8.6/http1.0
    /usr/local/TclHome/lib/tcl8.6/opt0.4
    /usr/local/TclHome/lib/tcl8.6/msgs
    /usr/local/TclHome/lib/tcl8.6/encoding
    /usr/local/TclHome/lib
}

# The child's ::auto_path must be given a suitable value:

safe::interpConfigure foo -autoPath {
    /usr/local/TclHome/lib/tcl8.6
    /usr/local/TclHome/lib
}

# The two commands can be combined:

safe::interpCreate foo -accessPath {
    /usr/local/TclHome/lib/tcl8.6
    /usr/local/TclHome/lib/tcl8.6/http1.0
    /usr/local/TclHome/lib/tcl8.6/opt0.4
    /usr/local/TclHome/lib/tcl8.6/msgs
    /usr/local/TclHome/lib/tcl8.6/encoding
    /usr/local/TclHome/lib
} -autoPath {
    /usr/local/TclHome/lib/tcl8.6
    /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), pkg_mkIndex(n), source(n),
tm(n), unknown(n)
.SH KEYWORDS
alias, auto-loading, auto_mkindex, load, parent interpreter, safe
interpreter, child interpreter, source
'\" Local Variables:
'\" mode: nroff
'\" End:

Changes to doc/scan.n.

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126


127
128

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
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.
.SS "MANDATORY CONVERSION CHARACTER"
.PP
The following conversion characters are supported:
.TP
\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
.
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
.
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
.
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
.
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
.
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.
.TP

\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
.
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
.
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
.
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
.
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
.
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).







<
|
<



<
|
<



<
|
<



<
|
<



<
|
<







<
|
<
|
>
>
|
<
>
|
<




<
|
<


<
|
<






<
|
<










<
|
<











<
|
<







82
83
84
85
86
87
88

89

90
91
92

93

94
95
96

97

98
99
100

101

102
103
104

105

106
107
108
109
110
111
112

113

114
115
116
117

118
119

120
121
122
123

124

125
126

127

128
129
130
131
132
133

134

135
136
137
138
139
140
141
142
143
144

145

146
147
148
149
150
151
152
153
154
155
156

157

158
159
160
161
162
163
164
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.
.SS "MANDATORY CONVERSION CHARACTER"
.PP
The following conversion characters are supported:

.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.

.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.

.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.

.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.

.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.

.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.
.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.

.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.

.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.

.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.

.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.

.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).

Changes to doc/seek.n.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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 \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







<
|
<


<
|
<



<
|
<







23
24
25
26
27
28
29

30

31
32

33

34
35
36

37

38
39
40
41
42
43
44
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 \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:

.IP \fBstart\fR 10

The new access position will be \fIoffset\fR bytes from the start
of the underlying file or device.

.IP \fBcurrent\fR 10

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.

.IP \fBend\fR 10

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

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
.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

\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:

.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).

.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).

.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

.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.

.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).

.TP
\fBself namespace\fR
.
This returns the name of the unique namespace of the object that the method
was invoked upon.

.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.

.TP
\fBself object\fR
.
This returns the name of the object that the method was invoked upon.

.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.







|











>
















>










>
















>









>






>





>












>




>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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 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
.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)

.SH KEYWORDS
read, write, variable
'\" Local Variables:
'\" mode: nroff
'\" fill-column: 78
'\" End:







|
>






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)
.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
.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

\fBoo::singleton\fI method \fR?\fIarg ...\fR?
.fi
.SH "CLASS HIERARCHY"
.nf
\fBoo::object\fR
   \(-> \fBoo::class\fR







|







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 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
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"

.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.

.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 {







>
















|
>







43
44
45
46
47
48
49
50
51
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.
.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
'\"
'\" Copyright (c) 1996 Sun Microsystems, Inc.
'\" 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.
'\"
.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
\fBsocket \fR?\fIoptions\fR? \fIhost port\fR
.sp
\fBsocket\fR \fB\-server \fIcommand\fR ?\fIoptions\fR? \fIport\fR

.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


|











|

<

>







1
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 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
.nf
\fBsocket \fR?\fIoptions\fR? \fIhost port\fR

\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
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:

.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.

.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.

.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.







>








>








>







45
46
47
48
49
50
51
52
53
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
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 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.

.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:

.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.

.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.

.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







>
|
>

|
>



















>











>





>







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
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
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.
.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
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:


.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

.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

.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.

.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.













.PP
.SH "EXAMPLES"
.PP
Here is a very simple time server:
.PP
.CS
proc Server {startTime channel clientaddr clientport} {







|
>
>












>

















>








>



|
>
>
>
>
>
>
>
>
>
>
>
>
>







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
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 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 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} {
235
236
237
238
239
240
241
242

243
244
245
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

'\" Local Variables:
'\" mode: nroff
'\" End:







|
>



262
263
264
265
266
267
268
269
270
271
272
273
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
'\" 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
(^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
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).

.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







|
<
<



|
>







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 \ex1A ,


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).
.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
.SH SYNOPSIS
\fBstring \fIoption arg \fR?\fIarg ...\fR?
.BE
.SH DESCRIPTION
.PP
Performs one of several string operations, depending on \fIoption\fR.
The legal \fIoption\fRs (which may be abbreviated) are:

.TP
\fBstring cat\fR ?\fIstring1\fR? ?\fIstring2...\fR?
.
Concatenate the given \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

.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.

.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.

.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







>














>










>









>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
.PP
.CS
\fBstring first a 0123456789abcdef 11\fR
.CE
.PP
will return \fB\-1\fR.
.RE

.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

.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"

.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







>












>


















>







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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
186
187
188
189
190
191
192

193
194
195
196
197
198
199
.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

.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







>







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
.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
.PP
.CS
\fBstring last a 0a23456789abcdef 9\fR
.CE
.PP
will return \fB1\fR.
.RE

.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.

.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







>








>







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
.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
.PP
.CS
\fBstring map {1 0 ab 2 a 3 abc 1} 1abcaababcabababc\fR
.CE
.PP
it will return the string \fB02c322c222c\fR.
.RE

.TP
\fBstring match\fR ?\fB\-nocase\fR? \fIpattern\fR \fIstring\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







>

|







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
.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 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
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

.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.

.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.

.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.

.TP
\fBstring reverse \fIstring\fR
.
Returns a string that is the same length as \fIstring\fR but with its
characters in the reverse order.

.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.

.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.

.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.

.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").

.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").

.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.
.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.

.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







>














>






>












|
|
>
|
>





>









>











>









>







>







>












<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









>







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
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.  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.










.\" METHOD: wordend





























.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
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"]
}
.CE
.SH "SEE ALSO"
expr(n), list(n)
.SH KEYWORDS
case conversion, compare, index, integer value, match, pattern, string, word, equal,
ctype, character, reverse
.\" Local Variables:
.\" mode: nroff
.\" End:







|





|
|



479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
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"]
}
.CE
.SH "SEE ALSO"
expr(n), list(n)
.SH KEYWORDS
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
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

.\" Local Variables:
.\" mode: nroff
.\" End:







|
>



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
.\" 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
.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:

.TP 10
\fB\-exact\fR
.
Use exact matching when comparing \fIstring\fR to a pattern.  This
is the default.

.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).

.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).

.TP 10
\fB\-nocase\fR
.
Causes comparisons to be handled in a case-insensitive manner.

.TP 10
\fB\-matchvar\fR \fIvarName\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.

.TP 10
\fB\-indexvar\fR \fIvarName\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.

.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.







>





>





>






>




>

|











>

|















>







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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\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\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
.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}}
.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     \-
    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 \-
    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 {
    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"
    }







|







|
|











|

















|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
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}}
.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     -
    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 -
    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 {
    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
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" .
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 ,
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







<
|



|
<
<
<







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,

.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 \ex1A ;



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
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.











.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):

.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.

.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.

.TP 15
\fBargv0\fR
.
Contains \fIfileName\fR if it was specified.
Otherwise, contains the name by which \fBtclsh\fR was invoked.

.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


.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







>
>
>
>
>
>
>
>
>
>
>





>





>





>





>







>
>







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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

Changes to doc/tcltest.n.

85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118
119
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

143
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211

212
213
214
215
216
217
218
\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

.TP
\fBtest\fR \fIname 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
.
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" .
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 \- .

.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.

.TP
\fBmakeFile\fR \fIcontents 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.

.TP
\fBremoveFile\fR \fIname\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.

.TP
\fBmakeDirectory\fR \fIname\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.

.TP
\fBremoveDirectory\fR \fIname\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.

.TP
\fBviewFile\fR \fIfile\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.

.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

.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"

.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







>

|













|




|





>









>

|














>

|






>

|








>

|







>

|











>




















>









>







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
\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\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\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\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\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\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\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\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\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
.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

.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.

.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.

.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.

.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.

.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"

.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?" .

.TP
\fBlimitConstraints\fR ?\fIboolean\fR?
.
Same as
.QW "\fBconfigure \-limitconstraints\fR ?\fIboolean\fR?" .

.TP
\fBloadFile\fR ?\fIfilename\fR?
.
Same as
.QW "\fBconfigure \-loadfile\fR ?\fIfilename\fR?" .

.TP
\fBloadScript\fR ?\fIscript\fR?
.
Same as
.QW "\fBconfigure \-load\fR ?\fIscript\fR?" .

.TP
\fBmatch\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-match\fR ?\fIpatternList\fR?" .

.TP
\fBmatchDirectories\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-relateddir\fR ?\fIpatternList\fR?" .

.TP
\fBmatchFiles\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-file\fR ?\fIpatternList\fR?" .

.TP
\fBoutputFile\fR ?\fIfilename\fR?
.
Same as
.QW "\fBconfigure \-outfile\fR ?\fIfilename\fR?" .

.TP
\fBpreserveCore\fR ?\fIlevel\fR?
.
Same as
.QW "\fBconfigure \-preservecore\fR ?\fIlevel\fR?" .

.TP
\fBsingleProcess\fR ?\fIboolean\fR?
.
Same as
.QW "\fBconfigure \-singleproc\fR ?\fIboolean\fR?" .

.TP
\fBskip\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-skip\fR ?\fIpatternList\fR?" .

.TP
\fBskipDirectories\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-asidefromdir\fR ?\fIpatternList\fR?" .

.TP
\fBskipFiles\fR ?\fIpatternList\fR?
.
Same as
.QW "\fBconfigure \-notfile\fR ?\fIpatternList\fR?" .

.TP
\fBtemporaryDirectory\fR ?\fIdirectory\fR?
.
Same as
.QW "\fBconfigure \-tmpdir\fR ?\fIdirectory\fR?" .

.TP
\fBtestsDirectory\fR ?\fIdirectory\fR?
.
Same as
.QW "\fBconfigure \-testdir\fR ?\fIdirectory\fR?" .

.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
.
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







>














>





>








>







>








>










>





>





>





>





>





>





>





>





>





>





>





>





>





>





>












|







244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
.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\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
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.

.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.

.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.

.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







>







>











>







>







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
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.
.\" COMMAND: bytestring
.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
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
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
        ?\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?







|







476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
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\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
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:

.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.


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.

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.


.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.

.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.

.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.

.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.

.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.

.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.

.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.

.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" .

.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







>










>
>



>









>
>







>









>







>








>






>









>









>











>







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
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
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
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
\fBtcltest\fR package itself:
.TP
\fIsingleTestInterp\fR
.
This test can only be run if all test files are sourced into a single
interpreter.
.TP
\fIunix\fR
.
This test can only be run on any Unix platform.
.TP
\fIwin\fR
.
This test can only be run on any Windows platform.
.TP
\fInt\fR
.
This test can only be run on any Windows NT platform.
.TP
\fImac\fR
.
This test can only be run on any Mac platform.
.TP
\fIunixOrWin\fR
.
This test can only be run on a Unix or Windows platform.
.TP
\fImacOrWin\fR
.
This test can only be run on a Mac or Windows platform.
.TP
\fImacOrUnix\fR
.
This test can only be run on a Mac or Unix platform.
.TP
\fItempNotWin\fR
.
This test can not be run on Windows.  This flag is used to temporarily
disable a test.
.TP
\fItempNotMac\fR
.
This test can not be run on a Mac.  This flag is used
to temporarily disable a test.
.TP
\fIunixCrash\fR
.
This test crashes if it is run on Unix.  This flag is used to temporarily
disable a test.
.TP
\fIwinCrash\fR
.
This test crashes if it is run on Windows.  This flag is used to temporarily
disable a test.
.TP
\fImacCrash\fR
.
This test crashes if it is run on a Mac.  This flag is used to temporarily
disable a test.
.TP
\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
.
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
.
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
.
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
.
This test can only be run in if the interpreter is in interactive mode
(when the global tcl_interactive variable is set to 1).
.TP
\fInonBlockFiles\fR
.
This test can only be run if platform supports setting files into
nonblocking mode.
.TP
\fIasyncPipeClose\fR
.
This test can only be run if platform supports async flush and async close
on a pipe.
.TP
\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
.
This test can only be run if can switch to an ISO locale.
.TP
\fIroot\fR
.
This test can only run if Unix user is root.
.TP
\fInotRoot\fR
.
This test can only run if Unix user is not root.
.TP
\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
.
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.







|






|

<
|
<


<
|
<

<
|
<

<
|
<

<
|
<

<
|
<

<
|
<

<
|
<

<
|
<


<
|
<


<
|
<


<
|
<


<
|
<


<
|
<




<
|
<



<
|
<





<
|
<



<
|
<

|
<
|
<


<
|
<


<
|
<



<
|
<

<
|
<

<
|
<

<
|
<




<
|
<







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
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 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 predefined by the
\fBtcltest\fR package itself:

.IP \fIsingleTestInterp\fR

This test can only be run if all test files are sourced into a single
interpreter.

.IP \fIunix\fR

This test can only be run on any Unix platform.

.IP \fIwin\fR

This test can only be run on any Windows platform.

.IP \fInt\fR

This test can only be run on any Windows NT platform.

.IP \fImac\fR

This test can only be run on any Mac platform.

.IP \fIunixOrWin\fR

This test can only be run on a Unix or Windows platform.

.IP \fImacOrWin\fR

This test can only be run on a Mac or Windows platform.

.IP \fImacOrUnix\fR

This test can only be run on a Mac or Unix platform.

.IP \fItempNotWin\fR

This test can not be run on Windows.  This flag is used to temporarily
disable a test.

.IP \fItempNotMac\fR

This test can not be run on a Mac.  This flag is used
to temporarily disable a test.

.IP \fIunixCrash\fR

This test crashes if it is run on Unix.  This flag is used to temporarily
disable a test.

.IP \fIwinCrash\fR

This test crashes if it is run on Windows.  This flag is used to temporarily
disable a test.

.IP \fImacCrash\fR

This test crashes if it is run on a Mac.  This flag is used to temporarily
disable a test.

.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.

.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.

.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.

.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.

.IP \fIinteractive\fR

This test can only be run in if the interpreter is in interactive mode
(when the global \fB::tcl_interactive\fR variable is set to 1).

.IP \fInonBlockFiles\fR

This test can only be run if platform supports setting files into
nonblocking mode.

.IP \fIasyncPipeClose\fR

This test can only be run if platform supports async flush and async close
on a pipe.

.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.

.IP \fIhasIsoLocale\fR

This test can only be run if can switch to an ISO locale.

.IP \fIroot\fR

This test can only run if Unix user is root.

.IP \fInotRoot\fR

This test can only run if Unix user is not root.

.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.

.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
\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:

.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.

.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:







>






>







839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
\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
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

.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







>







872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
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
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
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

.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

.TP
\fB\-limitconstraints \fIboolean\fR
.
Sets the mode by which \fBtest\fR honors constraints as described
in \fBTESTS\fR above.  Default value is false.

.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.

.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.

.TP
\fB\-testdir \fIdirectory\fR
.
Sets the directory searched by \fBrunAllTests\fR for test files
and subdirectories.  Default value is \fBworkingDirectory\fR.

.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 .

.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.

.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 .

.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.

.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 .

.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.

.TP
\fB\-load \fIscript\fR
.
Sets a script to be evaluated by \fBloadTestedCommands\fR.
Default value is an empty script.

.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.

.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.

.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.







|










>

















>





>







>








>





>






>







>







>






>






>





>





>






>






>







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
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 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
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







<







1190
1191
1192
1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
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 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
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.

.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
Additional variables relating to package management exist. More
details are listed in the \fBVARIABLES\fR section of the \fBlibrary\fR
manual page.
.RE

.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.







>













>
>
>
>






>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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,
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
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
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.


.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







|
<
<
|
|
>
>







75
76
77
78
79
80
81
82


83
84
85
86
87
88
89
90
91
92
93
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. The value of this variable


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
.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

.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.







>







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
.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
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

.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.

.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







>










>







216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
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
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.

.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.

.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.

.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
.
The native byte order of this machine: either \fBlittleEndian\fR or
\fBbigEndian\fR.
.TP
\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
.
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
.
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
.
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
.
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
'\" 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
.
Either \fBwindows\fR, or \fBunix\fR.  This identifies the
general operating environment of the machine.
.TP
\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
.
If this variable exists, then the interpreter
was compiled with threads enabled.
.TP
\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
.
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

.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.

.RE

.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.







>









>



















>












<
|
<


<
|
<





<
|
<


<
|
<



<
|
<



<
|
<


<
|



<
|
<


<
|
<


<
|
<


<
|
<




<
|
<



>

















>

>







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
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

.IP \fBbyteOrder\fR

The native byte order of this machine: either \fBlittleEndian\fR or
\fBbigEndian\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.

.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.

.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.

.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.

.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.

.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.

.IP \fBplatform\fR

Either \fBwindows\fR, or \fBunix\fR.  This identifies the
general operating environment of the machine.

.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.)

.IP \fBthreaded\fR

If this variable exists, then the interpreter
was compiled with threads enabled.

.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.

.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
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

.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).

.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
Unicode word character (number, letter, or underscore).

.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.

.TP 6
\fBargc\fR
.
The number of arguments to \fBtclsh\fR or \fBwish\fR.

.TP 6
\fBargv\fR
.
Tcl list of arguments to \fBtclsh\fR or \fBwish\fR.

.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.

.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







>











>











>















>




>




>






>







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
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).
.\" 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
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/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
'\"
'\" 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

\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?
.sp
\fBtimerate \fR?\fB\-calibrate\fR? ?\fB\-direct\fR? \fIscript\fR ?\fItime\fR? ?\fImax-count\fR?

.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
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
iterations is reached or the time is exceeded.
.sp
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])

.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])

.PP
The following options may be supplied to the \fBtimerate\fR command:

.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 calibration is not thread safe in the current implementation.
.RE

.TP
\fB\-overhead \fIdouble\fR
.
The \fB\-overhead\fR parameter supplies an estimate (in microseconds) 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.

.TP
\fB\-direct\fR
.
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.
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.
.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 {}













>

<
|
<

>
















|


|

|
|







|
>





|
>


>











>
|

>

|

|
>




>



|




|
|

|
|
|
>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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?

\fBtimerate \fR?\fB\-direct\fR? ?\fB\-overhead\fI estimate\fR? \fIscript\fR ?\fItime\fR? ?\fImax-count\fR?

\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.
.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 evaluation will stop either this count of
iterations is reached or the time is exceeded.
.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])
.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])
.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
implementation.
.RE
.\" OPTION: -overhead
.TP
\fB\-overhead \fIestimate\fR
.
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,
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 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.
.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

\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:
.PP
.CS
\fI# calibrate\fR
\fBtimerate\fR -calibrate {}

\fI# estimate overhead\fR
set tm 0







|
|
|







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:
.PP
.CS
\fI# calibrate\fR
\fBtimerate\fR -calibrate {}

\fI# estimate overhead\fR
set tm 0

Changes to doc/tm.n.

19
20
21
22
23
24
25


26
27
28
29
30
31
32
.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:


.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







>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.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
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

.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.

.TP
\fB::tcl::tm::path list\fR
.
Returns a list containing all registered module paths, in the order
that they are searched for modules.

.TP
\fB::tcl::tm::roots \fR?\fIpath\fR...?
.
Similar to \fBpath add\fR, and layered on top of it. This command
takes a list of paths, extends each with
.QW "\fBtcl\fIX\fB/site-tcl\fR" ,
and







>





>





>







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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...?
.
Similar to \fBpath add\fR, and layered on top of it. This command
takes a list of paths, extends each with
.QW "\fBtcl\fIX\fB/site-tcl\fR" ,
and
291
292
293
294
295
296
297




298
299
300
301
302
303
304
305
306
307
308
.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
.CE




.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
.QW "\fIImplementation Choices for Tcl Modules\fR"
(online at http://tip.tcl.tk/190.html)
.SH "KEYWORDS"
modules, package
.\" Local Variables:
.\" mode: nroff
.\" End:







>
>
>
>



|

|





296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
.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
.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 https://tip.tcl-lang.org/189.html), Tcl Improvement Proposal #190
.QW "\fIImplementation Choices for Tcl Modules\fR"
(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
.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:

.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
.
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







>






|







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\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
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
.
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







|












>




>







73
74
75
76
77
78
79
80
81
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\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
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.

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







>







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
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
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







>















>







>



>



>














|
>
>
|
>
|
|
|
>
|


<
<
<
<







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
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 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.




\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
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

.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

.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







>


>




>







>







>





>


>




>








>








>







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







307
308
309
310
311
312
313
314
315
316
317
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




















.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
'\"
'\" 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


\fBcmdPrefix \fIoption\fR ?\fIarg arg ...\fR?









.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













>
>
|
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
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 \fIchannelName cmdPrefix\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
.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.

.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.

.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.

.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
.
implies that the channel is writable.
.TP
\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.

.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

.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.

.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







>







>








>








<
|
<

<
|
<












>














>








>







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

73

74

75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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

.IP \fBwrite\fR

implies that the channel is writable.

.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
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.

.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

.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







>














>







129
130
131
132
133
134
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
}
.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]
} \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
.SH "SEE ALSO"







|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
}
.CE
.PP
Handle different reasons for a file to not be openable for reading:
.PP
.CS
\fBtry\fR {
    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
.SH "SEE ALSO"

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
.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
.br
\fBunload \fR?\fIswitches\fR? \fIfileName packageName 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
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:

.TP
\fB\-nocomplain\fR
.
Suppresses all error messages. If this switch is given, \fBunload\fR will
never report an error.

.TP
\fB\-keeplibrary\fR
.
This switch will prevent \fBunload\fR from issuing the operating system call
that will unload the library from the process.

.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
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
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
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.
.SS "UNLOAD HOOK PROTOTYPE"
.PP
The unload procedure must match the following prototype:
.PP
.CS
typedef int \fBTcl_PackageUnloadProc\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







|

|








|











>





>





>




















|

|
|

|









|
|
|
|





|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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 prefix\fR
.br
\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 \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
\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 \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 \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.
.SS "UNLOAD HOOK PROTOTYPE"
.PP
The unload procedure must match the following prototype:
.PP
.CS
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
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
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.
.SH "PORTABILITY ISSUES"
.TP
\fBUnix\fR\0\0\0\0\0
.
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







|


|
|
|
|
|
>
|
|
|
|
|


|







113
114
115
116
117
118
119
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 \fIprefix\fR argument must
be specified.
.PP
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
.
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
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.

.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.







|
>







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.
.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
.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).







<







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
    puts $name
}
proc \fIsetByUpvar\fR { name value } {
    \fBupvar\fR $name localVar
    set localVar $value
}
set originalVar 1
trace variable originalVar w \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
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







|



|
>
|
<
<
<







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 add variable originalVar write \fItraceproc\fR
\fIsetByUpvar\fR originalVar 2
.CE
.PP
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.



.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
'\"
'\" 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


.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 some cases the \fBvwait\fR command may not return immediately
after \fIvarName\fR 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













|
>
>












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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\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 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
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,
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.







|







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 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
'\"
'\" Copyright (c) 2015 Jan Nijtmans <[email protected]>
'\" Copyright (c) 2015 Christian Werner <[email protected]>
'\" Copyright (c) 2017 Sean Woods <[email protected]>
'\"
'\" 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"
.so man.macros
.BS
.SH NAME
TclZipfs_AppHook, Tclzipfs_Mount, TclZipfs_MountBuffer, Tclzipfs_Unmount \- handle ZIP files as Tcl virtual filesystems
.SH SYNOPSIS
.nf
int
\fBTclZipfs_AppHook(\fIargcPtr, argvPtr\fR)
.sp
int
\fBTclzipfs_Mount\fR(\fIinterp, mountpoint, zipname, password\fR)
.sp
int
\fBTclZipfs_MountBuffer\fR(\fIinterp, mountpoint, data, dataLen, copy\fR)
.sp
int
\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
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
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
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












|


|
|


|


|


|



















|
















|
|
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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) 2015 Jan Nijtmans <[email protected]>
'\" Copyright (c) 2015 Christian Werner <[email protected]>
'\" Copyright (c) 2017 Sean Woods <[email protected]>
'\"
'\" 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"
.so man.macros
.BS
.SH NAME
TclZipfs_AppHook, TclZipfs_Mount, TclZipfs_MountBuffer, TclZipfs_Unmount \- handle ZIP files as Tcl virtual filesystems
.SH SYNOPSIS
.nf
const char *
\fBTclZipfs_AppHook\fR(\fIargcPtr, argvPtr\fR)
.sp
int
\fBTclZipfs_Mount\fR(\fIinterp, zipname, mountpoint, password\fR)
.sp
int
\fBTclZipfs_MountBuffer\fR(\fIinterp, data, dataLen, mountpoint, copy\fR)
.sp
int
\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 "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\fBapp\fR as a read-only Tcl virtual file
system. \fIZIPFS_VOLUME\fR is \fB//zipfs:/\fR on all platforms.


.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
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
81
82
83
84
85
86
87
88
89
90

91
92
93
94
95


96
97




98


99
100
101




102
103
104
105
106
107
108
109


110
111
112
113
114
115
116
117
118
119
120
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.
.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
be compiled with the UNICODE preprocessor symbol defined (e.g., via the
\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
current implementation does not do so, but callers \fIshould not\fR assume
that this will be true in the future.
.PP


\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




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
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
call is a standard Tcl result code.


.PP
\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







|

|
>
|
|
<
|

>
>
|
|
>
>
>
>
|
>
>
|
|
|
>
>
>
>


|
|
<
|
|
<
>
>

|









79
80
81
82
83
84
85
86
87
88
89
90
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

116
117

118
119
120
121
122
123
124
125
126
127
128
129
130
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.
.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
be compiled with the UNICODE preprocessor symbol defined (e.g., via the
\fB\-DUNICODE\fR compiler flag).
.PP
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,

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
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 \fB/mt\fR would be
normalized to \fB//zipfs:/mt\fR. 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 content \fIdata\fR on the
mount point given in \fImountpoint\fR. Both \fImountpoint\fR and \fIdata\fR must

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

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
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
.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 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 root\fR
\fBzipfs unmount\fR \fImountpoint\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


simple encryption, sufficient to prevent casual inspection of their contents
but not able to prevent access by even a moderately determined attacker.









.TP
\fBzipfs canonical\fR ?\fImountpoint\fR? \fIfilename\fR ?\fIinZipfs\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.

.TP
\fBzipfs exists\fR \fIfilename\fR
.
Return 1 if the given filename exists in the mounted zipfs and 0 if it does not.

.TP
\fBzipfs find\fR \fIdirectoryName\fR
.
Recursively lists files including and below the directory \fIdirectoryName\fR.
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.

.TP
\fBzipfs info\fR \fIfile\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.

.RE

.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.




.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
in \fIzipfile\fR will appear to Tcl to be regular files at the mount point.
.RS
.PP










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.






.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

.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
.QW \fB//zipfs:/\fR .


.TP
\fBzipfs unmount \fImountpoint\fR
.
Unmounts a previously mounted ZIP archive mounted to \fImountpoint\fR.


.SS "ZIP CREATION COMMANDS"
This package also provides several commands to aid the creation of ZIP
archives as Tcl applications.

.TP
\fBzipfs mkzip\fR \fIoutfile 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
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

.TP
\fBzipfs mkimg\fR \fIoutfile 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.
.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
(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.


.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.
.RE

.TP
\fBzipfs mkkey\fR \fIpassword\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.

.TP
\fBzipfs lmkimg\fR \fIoutfile inlist\fR ?\fIpassword infile\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.

.TP
\fBzipfs lmkzip\fR \fIoutfile 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 "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
# $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
.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







|
|
|
|
|
|

|
|
|
|
|
|

|


|



<
|
|
>
>


>
>
>
>
>
>
>
>
>








>

|


>

|

|
<
>
|
|
>

|













|
|
>

>



|
|
>
>
>
>
>
|
>
>
>
>

|
|
|
>
|
<


>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
>
>
>
>
>








>




|
<
|
|
>
>




>
>



>

|












>

|













>
>











>

|



>

|





>

|














|





|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
.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 tcl::zipfs \fR?\fB1.0\fR?

\fBzipfs canonical\fR ?\fImountpoint\fR? \fIfilename\fR ?\fIZIPFS\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\fI outfile inlist\fR ?\fIpassword infile\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 root\fR
\fBzipfs unmount\fI mountpoint\fR
.fi
'\" The following subcommand is *UNDOCUMENTED*
'\" \fBzipfs mount_data\fR ?\fIdata\fR ?\fImountpoint\fR??
.BE
.SH DESCRIPTION
.PP

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?
.
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.
.\" METHOD: exists
.TP
\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\fI directoryName\fR
.
Returns the list of paths under directory \fIdirectoryName\fR which need not be

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\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
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?
.
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\fR
.TP
\fBzipfs mount\fI mountpoint\fR
.TP
\fBzipfs mount\fI zipfile mountpoint\fR ?\fIpassword\fR?

.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
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 \fB/mt\fR
would be normalized to \fB//zipfs:/mt\fR. 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: root
.TP
\fBzipfs root\fR
.
Returns a constant string which indicates the mount point for zipfs volumes
for the current platform.

This value is
.QW \fB//zipfs:/\fR
on most platforms.
.\" METHOD: unmount
.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\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
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\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.
.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
(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.
.RE
.\" METHOD: mkkey
.TP
\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\fI outfile inlist\fR ?\fIpassword infile\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\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 "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 $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 $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
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
.CE
.PP
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







|







266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
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 $zip $base $password
.CE
.PP
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

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
.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"

.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).

.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.

.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).

.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
.
The comment field from the header, if present.
.TP
\fBcrc\fR
.
A boolean value describing whether a CRC of the header is computed.
.TP
\fBfilename\fR
.
The filename field from the header, if present.
.TP
\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
.
The size of the uncompressed data.
.TP
\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
.
The type of the uncompressed data (\fBbinary\fR or \fBtext\fR) if known.
.RE

.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
.
Add the given comment to the header of the gzip-format data.
.TP
\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
.
The name of the file that the data to be compressed came from.
.TP
\fBos\fR
.
The operating system type code, which should be one of the values described in
RFC 1952.
.TP
\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
.
The type of the data being compressed, being \fBbinary\fR or \fBtext\fR.
.RE

.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"

.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
.
The transformation will be a compressing transformation that produces
zlib-format data on \fIchannel\fR, which must be writable.
.TP
\fBdecompress\fR
.
The transformation will be a decompressing transformation that reads
zlib-format data from \fIchannel\fR, which must be readable.
.TP
\fBdeflate\fR
.
The transformation will be a compressing transformation that produces raw
compressed data on \fIchannel\fR, which must be writable.
.TP
\fBgunzip\fR
.
The transformation will be a decompressing transformation that reads
gzip-format data from \fIchannel\fR, which must be readable.
.TP
\fBgzip\fR
.
The transformation will be a compressing transformation that produces
gzip-format data on \fIchannel\fR, which must be writable.
.TP
\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:

.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

.TP
\fB\-header\fI dictionary\fR
.
Passes a description of the gzip header to create, in the same format that
\fBzlib gzip\fR understands.

.TP
\fB\-level\fI compressionLevel\fR
.
How hard to compress the data. Must be an integer from 0 (uncompressed) to 9
(maximally compressed).

.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:

.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.

.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

.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.

.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.

.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"

.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:







>






>






>






>








<
|
<

<
|
<

<
|
<

<
|
<



<
|
<

<
|
<



<
|
<


>









<
|
<

<
|
<



<
|
<

<
|
<


<
|
<


<
|
<


>







>









<
|
<


<
|
<


<
|
<


<
|
<


<
|
<


<
|
<







>











>





>





>



















>







>











>









>






>








>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

54

55

56

57

58

59

60

61
62
63

64

65

66

67
68
69

70

71
72
73
74
75
76
77
78
79
80
81
82

83

84

85

86
87
88

89

90

91

92
93

94

95
96

97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

118

119
120

121

122
123

124

125
126

127

128
129

130

131
132

133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
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

.IP \fBcomment\fR

The comment field from the header, if present.

.IP \fBcrc\fR

A boolean value describing whether a CRC of the header is computed.

.IP \fBfilename\fR

The filename field from the header, if present.

.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.

.IP \fBsize\fR

The size of the uncompressed data.

.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.

.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

.IP \fBcomment\fR

Add the given comment to the header of the gzip-format data.

.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.

.IP \fBfilename\fR

The name of the file that the data to be compressed came from.

.IP \fBos\fR

The operating system type code, which should be one of the values described in
RFC 1952.

.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.

.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

.IP \fBcompress\fR

The transformation will be a compressing transformation that produces
zlib-format data on \fIchannel\fR, which must be writable.

.IP \fBdecompress\fR

The transformation will be a decompressing transformation that reads
zlib-format data from \fIchannel\fR, which must be readable.

.IP \fBdeflate\fR

The transformation will be a compressing transformation that produces raw
compressed data on \fIchannel\fR, which must be writable.

.IP \fBgunzip\fR

The transformation will be a decompressing transformation that reads
gzip-format data from \fIchannel\fR, which must be readable.

.IP \fBgzip\fR

The transformation will be a compressing transformation that produces
gzip-format data on \fIchannel\fR, which must be writable.

.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
.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"

.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.

.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:

.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" .

.TP
\fIstream \fBchecksum\fR
.
Returns the checksum of the uncompressed data seen so far by this stream.

.TP
\fIstream \fBclose\fR
.
Deletes this stream and frees up all resources associated with it.

.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.

.TP
\fIstream \fBfinalize\fR
.
A short-cut for
.QW "\fIstream \fBput \-finalize {}\fR" .

.TP
\fIstream \fBflush\fR
.
A short-cut for
.QW "\fIstream \fBput \-flush {}\fR" .

.TP
\fIstream \fBfullflush\fR
.
A short-cut for
.QW "\fIstream \fBput \-fullflush {}\fR" .

.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.

.
\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.

.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

.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

.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

.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

.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

.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







>





>














>







>




>




>






>





>





>





>






>
|





>








>






>













>











>













>







286
287
288
289
290
291
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
/*
 * colorings of characters
 * This file is #included by regcomp.c.
 *
 * Copyright (c) 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




|







1
2
3
4
5
6
7
8
9
10
11
12
/*
 * colorings of characters
 * This file is #included by regcomp.c.
 *
 * 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
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;

    fprintf(f, "max %ld\n", (long) 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);







|

|







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;
    const char *has;

    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
/*
 * Utility functions for handling cvecs
 * This file is #included by regcomp.c.
 *
 * Copyright (c) 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




|







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 © 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
/*
 * 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(
    int nchrs,			/* to hold this many chrs... */
    int nranges)		/* ... and this many ranges... */
{
    size_t nc = (size_t)nchrs + (size_t)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;







|



|
|

|







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(size_t, size_t);
 */
static struct cvec *
newcvec(
    size_t nchrs,		/* to hold this many chrs... */
    size_t nranges)		/* ... and this many ranges... */
{
    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
/*
 - 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... */
{
    if ((v->cv != NULL) && (nchrs <= v->cv->chrspace) &&
	    (nranges <= v->cv->rangespace)) {
	return clearcvec(v->cv);
    }

    if (v->cv != NULL) {







|
|







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 */
    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
/*
 * lexical analyzer
 * This file is #included by regcomp.c.
 *
 * Copyright (c) 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




|







1
2
3
4
5
6
7
8
9
10
11
12
/*
 * lexical analyzer
 * This file is #included by regcomp.c.
 *
 * 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
		FAILW(REG_BADBR);
	    }
	    break;
	case CHR('\\'):		/* BRE bound ends with \} */
	    if (INCON(L_BBND) && NEXT1('}')) {
		v->now++;
		INTOCON(L_BRE);
		RET('}');
	    } else {
		FAILW(REG_BADBR);
	    }
	    break;
	default:
	    FAILW(REG_BADBR);
	    break;







|







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);
		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
    if (!iscalnum(c)) {
	RETV(PLAIN, c);
    }

    NOTE(REG_UNONPOSIX);
    switch (c) {
    case CHR('a'):
	RETV(PLAIN, chrnamed(v, alert, ENDOF(alert), CHR('\007')));
	break;
    case CHR('A'):
	RETV(SBEGIN, 0);
	break;
    case CHR('b'):
	RETV(PLAIN, CHR('\b'));
	break;







|







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('\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
	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')));
	break;
    case CHR('f'):
	RETV(PLAIN, CHR('\f'));
	break;
    case CHR('m'):
	RET('<');
	break;







|







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('\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
	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);







<
<
<
<
<







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);
	}





	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
    chr c = (chr)pc;

    switch (c) {
    case CHR('*'):
	if (LASTTYPE(EMPTY) || LASTTYPE('(') || LASTTYPE('^')) {
	    RETV(PLAIN, c);
	}
	RET('*');
	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(']') &&







|







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);
	}
	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
/*
 * 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.
 *
 * 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'},
    {"space",		' '},
    {"exclamation-mark",'!'},
    {"quotation-mark",	'"'},
    {"number-sign",	'#'},
    {"dollar-sign",	'$'},
    {"percent-sign",	'%'},
    {"ampersand",	'&'},






|











|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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 © 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",		'\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
    {"grave-accent",	'`'},
    {"left-brace",	'{'},
    {"left-curly-bracket", '{'},
    {"vertical-line",	'|'},
    {"right-brace",	'}'},
    {"right-curly-bracket", '}'},
    {"tilde",		'~'},
    {"DEL",		'\177'},
    {NULL,		0}
};

/*
 * Unicode character-class tables.
 */








|







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",		'\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
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},
    {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},
    {0x1B83, 0x1BA0}, {0x1BBA, 0x1BE5}, {0x1C00, 0x1C23}, {0x1C4D, 0x1C4F},
    {0x1C5A, 0x1C7D}, {0x1C80, 0x1C88}, {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}
#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},

    {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},
    {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},
    {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},

    {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}
#endif
};

#define NUM_ALPHA_RANGE (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
#if CHRBITS > 16

    ,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
#endif
};

#define NUM_ALPHA_CHAR (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},
    {0xFFF9, 0xFFFB}
#if CHRBITS > 16
    ,{0x13430, 0x13438}, {0x1BCA0, 0x1BCA3}, {0x1D173, 0x1D17A}, {0xE0020, 0xE007F},
    {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}
#endif
};

#define NUM_CONTROL_RANGE (sizeof(controlRangeTable)/sizeof(crange))

static const chr controlCharTable[] = {
    0xAD, 0x61C, 0x6DD, 0x70F, 0x8E2, 0x180E, 0xFEFF
#if CHRBITS > 16
    ,0x110BD, 0x110CD, 0xE0001
#endif
};

#define NUM_CONTROL_CHAR (sizeof(controlCharTable)/sizeof(chr))

/*
 * Unicode: decimal digit characters.
 */

static const crange digitRangeTable[] = {
    {0x30, 0x39}, {0x660, 0x669}, {0x6F0, 0x6F9}, {0x7C0, 0x7C9},







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|








<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|






>
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
>
|


|
|
|
|
|
|
|
|
|
>
|
>
|
|
|
|
>
|
|



|










|
|
|
|
|
|
|
|
|
|

>
|
|
|


|
>
|
|
|
|



|







|
<

|
<



|


|





|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
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}, {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, 0x1B4C},
    {0x1B83, 0x1BA0}, {0x1BBA, 0x1BE5}, {0x1C00, 0x1C23}, {0x1C4D, 0x1C4F},
    {0x1C5A, 0x1C7D}, {0x1C80, 0x1C88}, {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, 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, 0xA7CA}, {0xA7D5, 0xA7D9}, {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}, {0x10600, 0x10736}, {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},
    {0x10E80, 0x10EA9}, {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}, {0x11400, 0x11434}, {0x11447, 0x1144A}, {0x1145F, 0x11461},
    {0x11480, 0x114AF}, {0x11580, 0x115AE}, {0x115D8, 0x115DB}, {0x11600, 0x1162F},
    {0x11680, 0x116AA}, {0x11700, 0x1171A}, {0x11740, 0x11746}, {0x11800, 0x1182B},
    {0x118A0, 0x118DF}, {0x118FF, 0x11906}, {0x1190C, 0x11913}, {0x11918, 0x1192F},
    {0x119A0, 0x119A7}, {0x119AA, 0x119D0}, {0x11A0B, 0x11A32}, {0x11A5C, 0x11A89},
    {0x11AB0, 0x11AF8}, {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},
    {0x14400, 0x14646}, {0x16800, 0x16A38}, {0x16A40, 0x16A5E}, {0x16A70, 0x16ABE},
    {0x16AD0, 0x16AED}, {0x16B00, 0x16B2F}, {0x16B40, 0x16B43}, {0x16B63, 0x16B77},
    {0x16B7D, 0x16B8F}, {0x16E40, 0x16E7F}, {0x16F00, 0x16F4A}, {0x16F93, 0x16F9F},
    {0x17000, 0x187F7}, {0x18800, 0x18CD5}, {0x18D00, 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}, {0x1E137, 0x1E13D}, {0x1E290, 0x1E2AD},
    {0x1E2C0, 0x1E2EB}, {0x1E4D0, 0x1E4EB}, {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 ((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, 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,
    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, 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, 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 ((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}, {0xFFF9, 0xFFFB}

#if CHRBITS > 16
    ,{0x13430, 0x1343F}, {0x1BCA0, 0x1BCA3}, {0x1D173, 0x1D17A}, {0xE0020, 0xE007F}

#endif
};

#define NUM_CONTROL_RANGE ((int)(sizeof(controlRangeTable)/sizeof(crange)))

static const chr controlCharTable[] = {
    0xAD, 0x61C, 0x6DD, 0x70F, 0x890, 0x891, 0x8E2, 0x180E, 0xFEFF
#if CHRBITS > 16
    ,0x110BD, 0x110CD, 0xE0001
#endif
};

#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},
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
    {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}
#endif
};

#define NUM_DIGIT_RANGE (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},
    {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},
    {0x16E97, 0x16E9A}, {0x1DA87, 0x1DA8B}
#endif
};

#define NUM_PUNCT_RANGE (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,
    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
#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

#endif
};

#define NUM_PUNCT_CHAR (sizeof(punctCharTable)/sizeof(chr))

/*
 * Unicode: white space characters.
 */

static const crange spaceRangeTable[] = {
    {0x9, 0xD}, {0x2000, 0x200B}
};

#define NUM_SPACE_RANGE (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))

/*
 * 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},
    {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},

    {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}

#endif
};

#define NUM_LOWER_RANGE (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,







>
|
|



|











|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
>
|
|



|





|
|
|
|

|
|
|
|
|



|
|
>



|









|






|
















|



|
>
|
|
|
|
|
|
|
>



|







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
    {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}, {0x11F50, 0x11F59}, {0x16A60, 0x16A69}, {0x16AC0, 0x16AC9},
    {0x16B50, 0x16B59}, {0x1D7CE, 0x1D7FF}, {0x1E140, 0x1E149}, {0x1E2F0, 0x1E2F9},
    {0x1E4F0, 0x1E4F9}, {0x1E950, 0x1E959}, {0x1FBF0, 0x1FBF9}
#endif
};

#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}, {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}, {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}
#if CHRBITS > 16
    ,{0x10100, 0x10102}, {0x10A50, 0x10A58}, {0x10AF0, 0x10AF6}, {0x10B39, 0x10B3F},
    {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}, {0x16E97, 0x16E9A},
    {0x1DA87, 0x1DA8B}
#endif
};

#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, 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, 0x1B7D, 0x1B7E, 0x1C7E, 0x1C7F, 0x1CD3,
    0x207D, 0x207E, 0x208D, 0x208E, 0x2329, 0x232A, 0x27C5, 0x27C6, 0x29FC,
    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, 0x116B9, 0x1183B, 0x119E2, 0x11C70, 0x11C71, 0x11EF7, 0x11EF8, 0x11FFF,
    0x12FF1, 0x12FF2, 0x16A6E, 0x16A6F, 0x16AF5, 0x16B44, 0x16FE2, 0x1BC9F, 0x1E95E,
    0x1E95F
#endif
};

#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 ((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 ((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, 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}, {0x10597, 0x105A1}, {0x105A3, 0x105B1},
    {0x105B3, 0x105B9}, {0x10CC0, 0x10CF2}, {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}, {0x1DF00, 0x1DF09}, {0x1DF0B, 0x1DF1E},
    {0x1DF25, 0x1DF2A}, {0x1E922, 0x1E943}
#endif
};

#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,
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
    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
#if CHRBITS > 16
    ,0x1D4BB, 0x1D7CB
#endif
};

#define NUM_LOWER_CHAR (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},
    {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},

    {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))

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,







|
|

|



|














|



|
>
|
|
|
|
|
|
<



|







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
    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, 0xA7D1, 0xA7D3, 0xA7D5, 0xA7D7, 0xA7D9, 0xA7F6, 0xA7FA
#if CHRBITS > 16
    ,0x105BB, 0x105BC, 0x1D4BB, 0x1D7CB
#endif
};

#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, 0x2C2F},
    {0x2C62, 0x2C64}, {0x2C6D, 0x2C70}, {0x2C7E, 0x2C80}, {0xA7AA, 0xA7AE},
    {0xA7B0, 0xA7B4}, {0xA7C4, 0xA7C7}, {0xFF21, 0xFF3A}
#if CHRBITS > 16
    ,{0x10400, 0x10427}, {0x104B0, 0x104D3}, {0x10570, 0x1057A}, {0x1057C, 0x1058A},
    {0x1058C, 0x10592}, {0x10C80, 0x10CB2}, {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 ((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,
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
    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

#if CHRBITS > 16
    ,0x1D49C, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D504, 0x1D505, 0x1D538,
    0x1D539, 0x1D546, 0x1D7CA
#endif
};

#define NUM_UPPER_CHAR (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},
    {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},
    {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},
    {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},
    {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},
    {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},
    {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},
    {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},
    {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}
#endif
};

#define NUM_GRAPH_RANGE (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,
    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
#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
#endif
};

#define NUM_GRAPH_CHAR (sizeof(graphCharTable)/sizeof(chr))

/*
 *	End of auto-generated Unicode character ranges declarations.
 */

/*
 - element - map collating-element name to celt







|
>

|
|



|









|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|





|






|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|







|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
>
|
>
|
|
|
|
|

>
|
|




|
|
>
|
>







|
|

|
|
|
|
|
|



|







|


|
|

|
|
|
|
|
|
>
|
|
|
|



|







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
    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, 0xA7D0, 0xA7D6,
    0xA7D8, 0xA7F5
#if CHRBITS > 16
    ,0x10594, 0x10595, 0x1D49C, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D504,
    0x1D505, 0x1D538, 0x1D539, 0x1D546, 0x1D7CA
#endif
};

#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}, {0x61D, 0x6DC}, {0x6DE, 0x70D},
    {0x710, 0x74A}, {0x74D, 0x7B1}, {0x7C0, 0x7FA}, {0x7FD, 0x82D},
    {0x830, 0x83E}, {0x840, 0x85B}, {0x860, 0x86A}, {0x870, 0x88E},
    {0x898, 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, 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, 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},
    {0x1B50, 0x1B7E}, {0x1B80, 0x1BF3}, {0x1BFC, 0x1C37}, {0x1C3B, 0x1C49},
    {0x1C4D, 0x1C88}, {0x1C90, 0x1CBA}, {0x1CBD, 0x1CC7}, {0x1CD0, 0x1CFA},

    {0x1D00, 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, 0x20C0}, {0x20D0, 0x20F0}, {0x2100, 0x218B},
    {0x2190, 0x2426}, {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, 0x31E3}, {0x31EF, 0x321E},
    {0x3220, 0xA48C}, {0xA490, 0xA4C6}, {0xA4D0, 0xA62B}, {0xA640, 0xA6F7},
    {0xA700, 0xA7CA}, {0xA7D5, 0xA7D9}, {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}, {0x1056F, 0x1057A}, {0x1057C, 0x1058A},
    {0x1058C, 0x10592}, {0x10597, 0x105A1}, {0x105A3, 0x105B1}, {0x105B3, 0x105B9},
    {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}, {0x10E60, 0x10E7E}, {0x10E80, 0x10EA9}, {0x10EAB, 0x10EAD},
    {0x10EFD, 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}, {0x11400, 0x1145B}, {0x1145D, 0x11461},
    {0x11480, 0x114C7}, {0x114D0, 0x114D9}, {0x11580, 0x115B5}, {0x115B8, 0x115DD},
    {0x11600, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C}, {0x11680, 0x116B9},
    {0x116C0, 0x116C9}, {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},
    {0x11AB0, 0x11AF8}, {0x11B00, 0x11B09}, {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, 0x11F59}, {0x11FC0, 0x11FF1}, {0x11FFF, 0x12399}, {0x12400, 0x1246E},
    {0x12470, 0x12474}, {0x12480, 0x12543}, {0x12F90, 0x12FF2}, {0x13000, 0x1342F},
    {0x13440, 0x13455}, {0x14400, 0x14646}, {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}, {0x1AFF0, 0x1AFF3}, {0x1AFF5, 0x1AFFB},
    {0x1B000, 0x1B122}, {0x1B150, 0x1B152}, {0x1B164, 0x1B167}, {0x1B170, 0x1B2FB},
    {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99},
    {0x1BC9C, 0x1BC9F}, {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},
    {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}, {0x1F900, 0x1FA53}, {0x1FA60, 0x1FA6D}, {0x1FA70, 0x1FA7C},
    {0x1FA80, 0x1FA88}, {0x1FA90, 0x1FABD}, {0x1FABF, 0x1FAC5}, {0x1FACE, 0x1FADB},
    {0x1FAE0, 0x1FAE8}, {0x1FAF0, 0x1FAF8}, {0x1FB00, 0x1FB92}, {0x1FB94, 0x1FBCA},
    {0x1FBF0, 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 ((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, 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, 0xA7D0, 0xA7D1, 0xA7D3, 0xFB3E, 0xFB40,
    0xFB41, 0xFB43, 0xFB44, 0xFDCF, 0xFFFC, 0xFFFD
#if CHRBITS > 16
    ,0x1003C, 0x1003D, 0x101A0, 0x10594, 0x10595, 0x105BB, 0x105BC, 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, 0x16FF0, 0x16FF1, 0x1AFFD,
    0x1AFFE, 0x1B132, 0x1B155, 0x1D49E, 0x1D49F, 0x1D4A2, 0x1D4A5, 0x1D4A6, 0x1D4BB,
    0x1D546, 0x1E023, 0x1E024, 0x1E08F, 0x1E14E, 0x1E14F, 0x1E2FF, 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, 0x1F8B0, 0x1F8B1
#endif
};

#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
    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;

    /*
     * 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_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
    };


    /*
     * 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;
    for (namePtr=classNames,i=0 ; *namePtr!=NULL ; namePtr++,i++) {
	if ((strlen(*namePtr) == len) && (strncmp(*namePtr, np, len) == 0)) {
	    index = 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) {



    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++) {







<
|











>


|














|


|




<
<
<
<













|
>
>
>







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
    int cases)			/* case-independent? */
{
    size_t len;
    struct cvec *cv = NULL;
    Tcl_DString ds;
    const char *np;
    const char *const *namePtr;

    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 = CC_NULL;
    for (namePtr=classNames,i=0 ; *namePtr!=NULL ; namePtr++,i++) {
	if ((strlen(*namePtr) == len) && (strncmp(*namePtr, np, len) == 0)) {
	    index = (enum classes)i;
	    break;
	}
    }
    Tcl_DStringFree(&ds);





    /*
     * 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 (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++) {

Changes to generic/regc_nfa.c.

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.
 *
 * 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




|







1
2
3
4
5
6
7
8
9
10
11
12
/*
 * NFA utilities.
 * This file is #included by regcomp.c.
 *
 * 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
    }
    while ((s = nfa->free) != NULL) {
	nfa->free = s->next;
	destroystate(nfa, s);
    }

    nfa->slast = NULL;
    nfa->nstates = -1;
    nfa->pre = NULL;
    nfa->post = NULL;
    FREE(nfa);
}

/*
 - newstate - allocate an NFA state, with zero flag value







|







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 = 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
	}
	nfa->v->spaceused += sizeof(struct state);
	s->oas.next = NULL;
	s->free = NULL;
	s->noas = 0;
    }

    assert(nfa->nstates >= 0);
    s->no = nfa->nstates++;
    s->flag = 0;
    if (nfa->states == NULL) {
	nfa->states = s;
    }
    s->nins = 0;
    s->ins = NULL;







|







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 != 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
    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.
 *
 * 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)
{







|







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 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)
{
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
 * 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







|







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 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
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
 * 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







|







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 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
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
 * 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







|







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 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
    struct nfa * nfa,
    struct state * ssource,
    struct state * sclone,
    struct state * spredecessor,
    struct arc * refarc,
    char *curdonemap,
    char *outerdonemap,
    int 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);







|







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,
    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
 */
static void
cleanup(
    struct nfa *nfa)
{
    struct state *s;
    struct state *nexts;
    int 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);







|







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;
    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);
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 */
analyze(
    struct nfa *nfa)
{
    struct arc *a;
    struct arc *aa;

    if (nfa->pre->outs == NULL) {







|







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 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
    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);
	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;







|







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(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
static void
dumpnfa(
    struct nfa *nfa,
    FILE *f)
{
#ifdef REG_DEBUG
    struct state *s;
    int nstates = 0;
    int narcs = 0;

    fprintf(f, "pre %d, post %d", 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);
    if (nfa->parent == NULL) {
	dumpcolors(nfa->cm, f);
    }
    fflush(f);
#else
    (void)nfa;
    (void)f;







|
|

|


















|







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;
    size_t nstates = 0;
    size_t narcs = 0;

    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 %" 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
static void
dumpstate(
    struct state *s,
    FILE *f)
{
    struct arc *a;

    fprintf(f, "%d%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",
		    a->from->no, a->to->no, s->no);
	}
    }
}

/*
 - dumparcs - dump out-arcs in human-readable form







|












|







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, "%" 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 %" 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
    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);
    }
    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);
    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 */







|



















|







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, "?%" 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, "%" 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
 */
static void
dumpcnfa(
    struct cnfa *cnfa,
    FILE *f)
{
#ifdef REG_DEBUG
    int st;

    fprintf(f, "pre %d, post %d", 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) {







|

|







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
    size_t st;

    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
static void
dumpcstate(
    int st,
    struct cnfa *cnfa,
    FILE *f)
{
    struct carc *ca;
    int 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);
	} else {
	    fprintf(f, "\t:%ld:->%d", (long) (ca->co - cnfa->ncolors), ca->to);
	}
	if (pos == 5) {
	    fprintf(f, "\n");
	    pos = 1;
	} else {
	    pos++;
	}







|





|

|







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;
    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[%d]->%" TCL_Z_MODIFIER "u", ca->co, ca->to);
	} else {
	    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
/*
 * re_*comp and friends - compile REs
 * This file #includes several others (see the bottom).
 *
 * Copyright (c) 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




|







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 © 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
			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);
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 *);







|







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 *, 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
#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 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);







|
|







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(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
     */

    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);
	}
	nfanode(v, &v->lacons[i], debug);
    }
    CNOERR();
    if (v->tree->flags&SHORTER) {
	NOTE(REG_USHORTEST);
    }







|







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 "u ==========\n", i);
	}
	nfanode(v, &v->lacons[i], debug);
    }
    CNOERR();
    if (v->tree->flags&SHORTER) {
	NOTE(REG_USHORTEST);
    }
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;

    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",
	    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,
		(g->lacons[i].subno) ? "positive" : "negative");
	dumpcnfa(&g->lacons[i].cnfa, f);
    }
    fprintf(f, "\n");
    dumpst(g->tree, f, 0);
#else
    (void)re;







|
















|








|







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;
    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 "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%" 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
	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);
    }
    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)));
    }







|







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, " %" 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
     * 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);
    } else {
	sprintf(buf, "%p", t);
    }
    return buf;
}

#include "regc_lex.c"
#include "regc_color.c"
#include "regc_nfa.c"







|

|







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) {
	snprintf(buf, bufsize, "%d", t->id);
    } else {
	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
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)







<



<
<
<
<
<







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 */

#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 */






/*
 * 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
/*
 * DFA routines
 * This file is #included by regexec.c.
 *
 * Copyright (c) 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




|







1
2
3
4
5
6
7
8
9
10
11
12
/*
 * DFA routines
 * This file is #included by regexec.c.
 *
 * 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
    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;
    struct colormap *cm = d->cm;

    /*
     * Initialize.
     */

    css = initialize(v, d, start);







|







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;
    size_t i;
    struct colormap *cm = d->cm;

    /*
     * Initialize.
     */

    css = initialize(v, d, start);
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
static chr *			/* endpoint, or NULL */
lastCold(
    struct vars *const v,
    struct dfa *const d)
{
    struct sset *ss;
    chr *nopr = d->lastnopr;
    int 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;







|







288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
static chr *			/* endpoint, or NULL */
lastCold(
    struct vars *const v,
    struct dfa *const d)
{
    struct sset *ss;
    chr *nopr = d->lastnopr;
    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;
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    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;
    struct smalldfa *smallwas = sml;

    assert(cnfa != NULL && cnfa->nstates != 0);

    if (nss <= FEWSTATES && cnfa->ncolors <= FEWCOLORS) {
	assert(wordsper == 1);
	if (sml == NULL) {







|







315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
    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;
    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
 - 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 i;
    unsigned h;

    h = 0;
    for (i = 0; i < n; i++) {
	h ^= uv[i];







|







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,
    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
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;

    /*
     * Is previous one still there?
     */

    if (d->nssused > 0 && (d->ssets[0].flags&STARTER)) {
	ss = &d->ssets[0];







|







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;
    size_t i;

    /*
     * Is previous one still there?
     */

    if (d->nssused > 0 && (d->ssets[0].flags&STARTER)) {
	ss = &d->ssets[0];
488
489
490
491
492
493
494

495
496
497
498
499
500
501
502
    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;

    int i, 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"));







>
|







488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
    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 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
		    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));
		}
	    }
	}
    }
    doLAConstraints = (gotState ? (cnfa->flags&HASLACONS) : 0);
    sawLAConstraints = 0;
    while (doLAConstraints) {		/* transitive closure */







|







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(("%" 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
		    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));
		}
	    }
	}
    }
    if (!gotState) {
	return NULL;
    }







|







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(("%" 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
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;
    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));
    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)));
    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.







|







|








|







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 */
{
    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 %" 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 %" 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
    chr *ancient;

    /*
     * Shortcut for cases where cache isn't full.
     */

    if (d->nssused < d->nssets) {
	i = d->nssused;
	d->nssused++;
	ss = &d->ssets[i];
	FDEBUG(("new c%d\n", i));

	/*
	 * Set up innards.
	 */

	ss->states = &d->statesarea[i * 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];
	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 */
	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)));
	    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)));
	    return ss;
	}
    }

    /*
     * Nobody's old enough?!? -- something's really wrong.
     */







|

|
|





|



|
|











|








|







|







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
    chr *ancient;

    /*
     * Shortcut for cases where cache isn't full.
     */

    if (d->nssused < d->nssets) {
	size_t j = d->nssused;
	d->nssused++;
	ss = &d->ssets[j];
	FDEBUG(("new c%" TCL_Z_MODIFIER "u\n", j));

	/*
	 * Set up innards.
	 */

	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[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 ((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%" 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%" TCL_Z_MODIFIER "u\n", (size_t)(ss - d->ssets)));
	    return ss;
	}
    }

    /*
     * Nobody's old enough?!? -- something's really wrong.
     */

Changes to generic/regerror.c.

1
2
3
4
5
6
7
8
9
10
11
/*
 * regerror - error-code expansion
 *
 * Copyright (c) 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



|







1
2
3
4
5
6
7
8
9
10
11
/*
 * regerror - error-code expansion
 *
 * 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
    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 */
	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);
	    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);
	    msg = convbuf;
	}
	break;
    }

    len = strlen(msg) + 1;	/* Space needed, including NUL */
    if (errbuf_size > 0) {







|












|












|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
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;
	    }
	}
	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 */
	    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 */
	    snprintf(convbuf, sizeof(convbuf), unk, code);
	    msg = convbuf;
	}
	break;
    }

    len = strlen(msg) + 1;	/* Space needed, including NUL */
    if (errbuf_size > 0) {

Changes to generic/regexec.c.

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.
 *
 * 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



|







1
2
3
4
5
6
7
8
9
10
11
/*
 * re_*exec and friends - match REs
 *
 * 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
    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 */

    int ncolors;		/* length of outarc and inchain vectors */
    int wordsper;		/* length of state-set bitvectors */
    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.







|
|
|
>

|










<







53
54
55
56
57
58
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 {
    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 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 */

    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
};
#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))

/*
 * forward declarations
 */
/* =====^!^===== begin forwards =====^!^===== */
/* automatically gathered by fwd; do not hand-edit */
/* === regexec.c === */







|







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)	((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
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 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 =====^!^===== */







|







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, 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
    }
    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)
	v->subdfas = subdfas;
    else
	v->subdfas = (struct dfa **) MALLOC(n * sizeof(struct dfa *));

    if (v->subdfas == NULL) {
	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;

    /*







|

|

>

|

>







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) {
	v->subdfas = subdfas;
    } else {
	v->subdfas = (struct dfa **) MALLOC(n * sizeof(struct dfa *));
    }
    if (v->subdfas == NULL) {
	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
     */

    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)
	    freeDFA(v->subdfas[i]);
    }

    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())
	    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 *);







|

|
>
|

>















|

>







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
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) {
	    freeDFA(v->subdfas[i]);
	}
    }
    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()) {
	    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
    /*
     * 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)));
    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) {







|







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 %" 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
    /*
     * Find starting point and match.
     */

    assert(cold != NULL);
    open = cold;
    cold = NULL;
    MDEBUG(("between %ld and %ld\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)));
	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);







|




|







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 %" 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 %" 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
    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)));
	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)));
	for (begin = open; begin <= close; begin++) {
	    MDEBUG(("\ncomplicatedFind trying at %ld\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)));
		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);
		    }







|







|

|















|







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 %" 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 %" TCL_Z_MODIFIER "u and %" TCL_Z_MODIFIER "u\n", LOFF(open), LOFF(close)));
	for (begin = open; begin <= close; 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 %" 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
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;
    }
}

/*
 - 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;
	assert(n > 0);
	if ((size_t) n < v->nmatch) {
	    v->pmatch[n].rm_so = -1;
	    v->pmatch[n].rm_eo = -1;
	}
    }

    if (t->left != NULL) {
	zaptreesubs(v, t->left);
    }
    if (t->right != NULL) {







|
|













|

|
|
|







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 = 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 == '(') {
	size_t n = t->subno;
	assert(n > 0);
	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
    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));

    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 */
	    er = crevcondissect(v, t, begin, end);
	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 */
	    er = creviterdissect(v, t, begin, end);
	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);







|












|

|

>







|

|

>







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 %" 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 */
	    er = crevcondissect(v, t, begin, end);
	} 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 */
	    er = creviterdissect(v, t, begin, end);
	} 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
    /*
     * 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)));

    /*
     * Iterate until satisfaction or failure.
     */

    for (;;) {
	/*







|







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 %" 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
	    /*
	     * 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)));
	zaptreesubs(v, t->left);
	zaptreesubs(v, t->right);
    }
}

/*
 - crevcondissect - dissect match for concatenation node, shortest-first







|







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 %" 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
     * 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)));

    /*
     * Iterate until satisfaction or failure.
     */

    for (;;) {
	/*







|







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 %" 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
	    /*
	     * 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)));
	zaptreesubs(v, t->left);
	zaptreesubs(v, t->right);
    }
}

/*
 - cbrdissect - dissect match for backref node







|







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 %" 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
    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) {
	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) {







|







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 == 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
    /*
     * 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)
	return REG_NOMATCH;

    numreps = tlen / brlen;
    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)
	    return REG_NOMATCH;

	p += brlen;
    }

    MDEBUG(("cbackref matched\n"));
    return REG_OKAY;
}








|

>

|

>




|

>







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) {
	return REG_NOMATCH;
    }
    numreps = tlen / brlen;
    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) {
	    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
    /*
     * 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)
	    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)
	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;








|

>













|

>







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) {
	    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) {
	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
	/* 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",
		t->id, k, LOFF(endpts[k])));

	/* k'th sub-match can no longer be considered verified */
	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;







|



|

>







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: %" TCL_Z_MODIFIER "u\n",
		t->id, k, LOFF(endpts[k])));

	/* k'th sub-match can no longer be considered verified */
	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

	/*
	 * 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)
	    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)
		break;

	    /* oops, something failed */
	    FREE(endpts);
	    return er;
	}

	if (i > k) {
	    /* satisfaction */







|

>










|

>







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) {
	    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) {
		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
    /*
     * 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)
	    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







|

>







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) {
	    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
	/* 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)
	    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",
		t->id, k, LOFF(endpts[k])));

	/* k'th sub-match can no longer be considered verified */
	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)
	    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)
		break;

	    /* oops, something failed */
	    FREE(endpts);
	    return er;
	}

	if (i > k) {
	    /* satisfaction */







|

>









|



|

>




















|

>










|

>







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) {
	    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: %" TCL_Z_MODIFIER "u\n",
		t->id, k, LOFF(endpts[k])));

	/* k'th sub-match can no longer be considered verified */
	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) {
	    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) {
		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
/*
 * regfree - free an RE
 *
 * Copyright (c) 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



|







1
2
3
4
5
6
7
8
9
10
11
/*
 * regfree - free an RE
 *
 * 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
/*
 * 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.
 *
 * 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






|







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 © 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

/*
 * 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 */
    chr *chrs;			/* pointer to vector of chrs */
    int nranges;		/* number of ranges (chr pairs) */
    int rangespace;		/* number of chrs possible */
    chr *ranges;		/* pointer to vector of chr pairs */
};

/*
 * definitions for non-deterministic finite autmaton (NFA) internal
 * representation
 *







|
|

|
|







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 {
    size_t nchrs;		/* number of chrs */
    size_t chrspace;		/* number of chrs possible */
    chr *chrs;			/* pointer to vector of chrs */
    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
struct arcbatch {		/* for bulk allocation of arcs */
    struct arcbatch *next;
#define	ABSIZE	10
    struct arc a[ABSIZE];
};

struct state {
    int no;
#define	FREESTATE	(-1)
    char flag;			/* marks special states */
    int nins;			/* number of inarcs */
    struct arc *ins;		/* chain of inarcs */
    int 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 */
};

struct nfa {
    struct state *pre;		/* pre-initial state */
    struct state *init;		/* initial state */
    struct state *final;	/* final state */
    struct state *post;		/* post-final state */
    int 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 */







|
|

|

|






|



|


|
|







238
239
240
241
242
243
244
245
246
247
248
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 {
    size_t no;
#define	FREESTATE	((size_t)-1)
    char flag;			/* marks special states */
    size_t nins;		/* number of inarcs */
    struct arc *ins;		/* chain of inarcs */
    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 */
    size_t noas;		/* number of arcs used in first arcbatch */
};

struct nfa {
    struct state *pre;		/* preinitial state */
    struct state *init;		/* initial state */
    struct state *final;	/* final state */
    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
 * 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 */
};

struct cnfa {
    int 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 */
    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 */







|



|



|
|







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 */
    size_t to;			/* next-state number */
};

struct cnfa {
    size_t nstates;	/* number of states */
    int ncolors;		/* number of colors */
    int flags;
#define	HASLACONS	01	/* uses lookahead constraints */
    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
    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 */
    struct colormap cmap;
    int (*compare) (const chr *, const chr *, size_t);
    struct subre *lacons;	/* lookahead-constraint vector */
    int nlacons;		/* size of lacons */
};

/*
 * Magic for allocating a variable workspace. This default version is
 * stack-hungry.
 */








|



|







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 */
    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 */
    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
# 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 <[email protected]>
#
# 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:







|
|
|







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 © 1998-1999 Scriptics Corporation.
# Copyright © 2001, 2002 Kevin B. Kenny.  All rights reserved.
# Copyright © 2007 Daniel A. Steffen <[email protected]>
#
# 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
	    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)
}
declare 4 {
    void Tcl_Free(void *ptr)
}
declare 5 {
    void *Tcl_Realloc(void *ptr, size_t size)
}
declare 6 {
    void *Tcl_DbCkalloc(size_t 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,
	    const char *file, int line)
}

# 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 {
    void Tcl_CreateFileHandler(int fd, int mask, Tcl_FileProc *proc,
	    void *clientData)
}
declare 10 unix {
    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)
}
declare 17 {
    Tcl_Obj *Tcl_ConcatObj(int 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)
}
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,
	    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,
	    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)
}
declare 32 {
    int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    int *boolPtr)
}

declare 33 {
    unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr, int *lengthPtr)
}
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)
}
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)
}
declare 46 {
    int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, int index,
	    Tcl_Obj **objPtrPtr)
}
declare 47 {
    int Tcl_ListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    int *lengthPtr)
}
declare 48 {
    int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, int first,
	    int count, int 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)
}
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[])
}
# 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)
}
# 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)
}
declare 59 {
    void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, const unsigned char *bytes,
	    size_t length)
}
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[])
}
# 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)
}
declare 65 {
    void Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes, size_t 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 {







|





|


|





|



|



|



|


















|


|














<
<
<
<

|
|






|


<
<
<
<




|









|



|

>

|








<
<
<
<
<













|













|
|


|



|
|


|
|

<
<
<
<

|




<
<
<
<

|

<
<
<
<




|

<
<
<
<

|



|




<
<
<
<

|

<
<
<
<

|


|

<
<
<
<
<
<
<
<
<







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106




107
108
109
110
111
112
113
114
115
116
117
118




119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149





150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191




192
193
194
195
196
197




198
199
200




201
202
203
204
205
206




207
208
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(TCL_HASH_TYPE size)
}
declare 4 {
    void Tcl_Free(void *ptr)
}
declare 5 {
    void *Tcl_Realloc(void *ptr, TCL_HASH_TYPE size)
}
declare 6 {
    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, TCL_HASH_TYPE size,
	    const char *file, int line)
}

# 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 {
    void Tcl_CreateFileHandler(int fd, int mask, Tcl_FileProc *proc,
	    void *clientData)
}
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, Tcl_Size length)
}
declare 17 {
    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)
}




declare 23 {
    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(Tcl_Size objc, Tcl_Obj *const *objv,
	    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, 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 *intPtr)
}
declare 32 {
    int Tcl_GetBooleanFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    int *intPtr)
}
# Only available in Tcl 8.x, NULL in Tcl 9.0
declare 33 {
    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)
}





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 *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 TclListObjGetElements(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    void *objcPtr, Tcl_Obj ***objvPtr)
}
declare 46 {
    int Tcl_ListObjIndex(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size index,
	    Tcl_Obj **objPtrPtr)
}
declare 47 {
    int TclListObjLength(Tcl_Interp *interp, Tcl_Obj *listPtr,
	    void *lengthPtr)
}
declare 48 {
    int Tcl_ListObjReplace(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Size first,
	    Tcl_Size count, Tcl_Size objc, Tcl_Obj *const objv[])
}




declare 50 {
    Tcl_Obj *Tcl_NewByteArrayObj(const unsigned char *bytes, Tcl_Size numBytes)
}
declare 51 {
    Tcl_Obj *Tcl_NewDoubleObj(double doubleValue)
}




declare 53 {
    Tcl_Obj *Tcl_NewListObj(Tcl_Size objc, Tcl_Obj *const objv[])
}




declare 55 {
    Tcl_Obj *Tcl_NewObj(void)
}
declare 56 {
    Tcl_Obj *Tcl_NewStringObj(const char *bytes, Tcl_Size length)
}




declare 58 {
    unsigned char *Tcl_SetByteArrayLength(Tcl_Obj *objPtr, Tcl_Size numBytes)
}
declare 59 {
    void Tcl_SetByteArrayObj(Tcl_Obj *objPtr, const unsigned char *bytes,
	    Tcl_Size numBytes)
}
declare 60 {
    void Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue)
}




declare 62 {
    void Tcl_SetListObj(Tcl_Obj *objPtr, Tcl_Size objc, Tcl_Obj *const objv[])
}




declare 64 {
    void Tcl_SetObjLength(Tcl_Obj *objPtr, Tcl_Size length)
}
declare 65 {
    void Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes, Tcl_Size 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
}
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)
#}

declare 82 {
    int Tcl_CommandComplete(const char *cmd)
}
declare 83 {
    char *Tcl_Concat(int argc, const char *const *argv)
}
declare 84 {
    size_t Tcl_ConvertElement(const char *src, char *dst, int flags)
}
declare 85 {
    size_t Tcl_ConvertCountedElement(const char *src, size_t length, char *dst,
	    int flags)
}
declare 86 {
    int Tcl_CreateAlias(Tcl_Interp *childInterp, const char *childCmd,
	    Tcl_Interp *target, const char *targetCmd, int 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_Obj *const objv[])
}
declare 88 {
    Tcl_Channel Tcl_CreateChannel(const Tcl_ChannelType *typePtr,
	    const char *chanName, void *instanceData, int mask)
}
declare 89 {







<
<
<
<
<
<
<
<











|
|
|
<
>




|


|


|




|




|







244
245
246
247
248
249
250








251
252
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
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)
}








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)
}
# 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(Tcl_Size argc, const char *const *argv)
}
declare 84 {
    Tcl_Size Tcl_ConvertElement(const char *src, char *dst, int flags)
}
declare 85 {
    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, Tcl_Size argc,
	    const char *const *argv)
}
declare 87 {
    int Tcl_CreateAliasObj(Tcl_Interp *childInterp, const char *childCmd,
	    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
}
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_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,







<
<
<
<
<
<















|







309
310
311
312
313
314
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)
}






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, 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
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)
}
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)
}
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)
}
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 {







|


















|




















|













<
<
<
<



<
<
<
<







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(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, 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, 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)
}




declare 130 {
    int Tcl_EvalFile(Tcl_Interp *interp, const char *fileName)
}




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
}
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,
	    Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
	    int *objcPtr, Tcl_Obj ***objv)
}
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)
}
declare 153 {
    int Tcl_GetChannelHandle(Tcl_Channel chan, int direction,
	    void **handlePtr)
}
declare 154 {
    void *Tcl_GetChannelInstanceData(Tcl_Channel chan)







<
<
<
<







<
<
<
<
|


















|







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
}
declare 142 {
    int Tcl_ExprString(Tcl_Interp *interp, const char *expr)
}
declare 143 {
    void Tcl_Finalize(void)
}




declare 145 {
    Tcl_HashEntry *Tcl_FirstHashEntry(Tcl_HashTable *tablePtr,
	    Tcl_HashSearch *searchPtr)
}
declare 146 {
    int Tcl_Flush(Tcl_Channel chan)
}




declare 148 {deprecated {Use Tcl_GetAliasObj}} {
    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,
	    Tcl_Interp **targetInterpPtr, const char **targetCmdPtr,
	    int *objcPtr, Tcl_Obj ***objv)
}
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 {
    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
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)
}
# 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)
}
declare 170 {
    size_t 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)
}







|
|
|







|


|










<
<
<
<
<
<
<
<
<




<
<
<
<
<
<
<
<







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
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 {
    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 {
    Tcl_Size Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr)
}
declare 170 {
    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)
}









declare 176 {
    const char *Tcl_GetVar2(Tcl_Interp *interp, const char *part1,
	    const char *part2, int flags)
}








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
    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,
	    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)
}
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,
	    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)
}
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)
}
declare 206 {
    size_t Tcl_Read(Tcl_Channel chan, char *bufPtr, size_t toRead)
}
declare 207 {
    void Tcl_ReapDetachedProcs(void)
}
declare 208 {
    int Tcl_RecordAndEval(Tcl_Interp *interp, const char *cmd, int 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
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
    int Tcl_InterpDeleted(Tcl_Interp *interp)
}
declare 185 {
    int Tcl_IsSafe(Tcl_Interp *interp)
}
# Obsolete, use Tcl_FSJoinPath
declare 186 {
    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 191 {
    Tcl_Channel Tcl_MakeTcpClientChannel(void *tcpSocket)
}
declare 192 {
    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, 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 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, int position)
}
declare 206 {
    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
	    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,
	    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)
}
declare 219 {
    size_t Tcl_ScanCountedElement(const char *src, size_t 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)
}
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)
}
# 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,
	    const char ***argvPtr)
}
# Obsolete, use Tcl_FSSplitPath
declare 243 {
    void Tcl_SplitPath(const char *path, int *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)
}
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)
}
declare 264 {
    void Tcl_WrongNumArgs(Tcl_Interp *interp, int 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)
}








|









|


|

<
<
<
<











|


















<
<
<
<

|

<
<
<
<
<












<
<
<
<
<














|




|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









|







<
<
<
<




<
<
<
<
<








<
<
<
<
<







<
<
<
<
<






|


|








<
<
<
<
<
<
<
<







<
<
<
<
<





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



<
<
<
<







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
	    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, 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 {
    Tcl_Size Tcl_ScanElement(const char *src, int *flagPtr)
}
declare 219 {
    Tcl_Size Tcl_ScanCountedElement(const char *src, Tcl_Size length, int *flagPtr)
}




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, 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)
}




declare 231 {
    Tcl_Size Tcl_SetRecursionLimit(Tcl_Interp *interp, Tcl_Size depth)
}





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)
}





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 TclSplitList(Tcl_Interp *interp, const char *listStr, void *argcPtr,
	    const char ***argvPtr)
}
# Obsolete, use Tcl_FSSplitPath
declare 243 {
    void TclSplitPath(const char *path, void *argcPtr, const char ***argvPtr)
}


















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 {
    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)
}




declare 254 {
    int Tcl_UnsetVar2(Tcl_Interp *interp, const char *part1, const char *part2,
	    int flags)
}





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)
}





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, ...)
}





declare 262 {
    void *Tcl_VarTraceInfo2(Tcl_Interp *interp, const char *part1,
	    const char *part2, int flags, Tcl_VarTraceProc *procPtr,
	    void *prevClientData)
}
declare 263 {
    Tcl_Size Tcl_Write(Tcl_Channel chan, const char *s, Tcl_Size slen)
}
declare 264 {
    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)
}








declare 269 {
    char *Tcl_HashStats(Tcl_HashTable *tablePtr)
}
declare 270 {
    const char *Tcl_ParseVar(Tcl_Interp *interp, const char *start,
	    const char **termPtr)
}





declare 272 {
    const char *Tcl_PkgPresentEx(Tcl_Interp *interp,
	    const char *name, const char *version, int exact,
	    void *clientDataPtr)
}



















declare 277 {
    Tcl_Pid Tcl_WaitPid(Tcl_Pid pid, int *statPtr, int options)
}




declare 279 {
    void Tcl_GetVersion(int *major, int *minor, int *patchLevel, int *type)
}
declare 280 {
    void Tcl_InitMemory(Tcl_Interp *interp)
}

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
}
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 flags)
}
declare 292 {
    int Tcl_EvalObjv(Tcl_Interp *interp, int 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,
	    int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr)
}
declare 296 {
    char *Tcl_ExternalToUtfDString(Tcl_Encoding encoding,
	    const char *src, size_t srcLen, Tcl_DString *dsPtr)
}
declare 297 {
    void Tcl_FinalizeThread(void)
}
declare 298 {
    void Tcl_FinalizeNotifier(void *clientData)
}







<
<
<
<

|



|










|
|




|







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
}
declare 288 {
    void Tcl_CreateThreadExitHandler(Tcl_ExitProc *proc, void *clientData)
}
declare 289 {
    void Tcl_DeleteThreadExitHandler(Tcl_ExitProc *proc, void *clientData)
}




declare 291 {
    int Tcl_EvalEx(Tcl_Interp *interp, const char *script, Tcl_Size numBytes,
	    int flags)
}
declare 292 {
    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, 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, 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
    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)
}
declare 305 {
    void *Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr, size_t size)
}
declare 306 {
    Tcl_Obj *Tcl_GetVar2Ex(Tcl_Interp *interp, const char *part1,
	    const char *part2, int flags)
}
declare 307 {
    void *Tcl_InitNotifier(void)







|
|


|







941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
    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, Tcl_Size offset, const char *msg, int flags,
	    void *indexPtr)
}
declare 305 {
    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
    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)
}
declare 313 {
    size_t Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr,
	    size_t 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)
}
declare 320 {
    int Tcl_UniCharAtIndex(const char *src, size_t 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)
}
declare 325 {
    const char *Tcl_UtfAtIndex(const char *src, size_t index)
}
declare 326 {
    int Tcl_UtfCharComplete(const char *src, size_t length)
}
declare 327 {
    size_t 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)
}
declare 331 {
    const char *Tcl_UtfPrev(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,
	    int *srcReadPtr, int *dstWrotePtr, int *dstCharsPtr)
}
declare 333 {
    char *Tcl_UtfToExternalDString(Tcl_Encoding encoding,
	    const char *src, size_t srcLen, Tcl_DString *dsPtr)
}
declare 334 {
    int Tcl_UtfToLower(char *src)
}
declare 335 {
    int Tcl_UtfToTitle(char *src)
}
declare 336 {
    int Tcl_UtfToChar16(const char *src, unsigned short *chPtr)
}
declare 337 {
    int Tcl_UtfToUpper(char *src)
}
declare 338 {
    size_t Tcl_WriteChars(Tcl_Channel chan, const char *src, size_t srcLen)
}
declare 339 {
    size_t 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 {







|


|
|

<
<
<
<
<
<
<
<












|


|











|


|


|


|








|


|



|
|




|


|


|


|


|


|


|




<
<
<
<
<
<
<
<







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
    void Tcl_ConditionNotify(Tcl_Condition *condPtr)
}
declare 311 {
    void Tcl_ConditionWait(Tcl_Condition *condPtr, Tcl_Mutex *mutexPtr,
	    const Tcl_Time *timePtr)
}
declare 312 {
    Tcl_Size TclNumUtfChars(const char *src, Tcl_Size length)
}
declare 313 {
    Tcl_Size Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr,
	    Tcl_Size charsToRead, int appendFlag)
}








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,
	    int position)
}
declare 320 {
    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 {
    Tcl_Size Tcl_UniCharToUtf(int ch, char *buf)
}
declare 325 {
    const char *TclUtfAtIndex(const char *src, Tcl_Size index)
}
declare 326 {
    int TclUtfCharComplete(const char *src, Tcl_Size length)
}
declare 327 {
    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 *TclUtfNext(const char *src)
}
declare 331 {
    const char *TclUtfPrev(const char *src, const char *start)
}
declare 332 {
    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)
}
declare 333 {
    char *Tcl_UtfToExternalDString(Tcl_Encoding encoding,
	    const char *src, Tcl_Size srcLen, Tcl_DString *dsPtr)
}
declare 334 {
    Tcl_Size Tcl_UtfToLower(char *src)
}
declare 335 {
    Tcl_Size Tcl_UtfToTitle(char *src)
}
declare 336 {
    Tcl_Size Tcl_UtfToChar16(const char *src, unsigned short *chPtr)
}
declare 337 {
    Tcl_Size Tcl_UtfToUpper(char *src)
}
declare 338 {
    Tcl_Size Tcl_WriteChars(Tcl_Channel chan, const char *src, Tcl_Size srcLen)
}
declare 339 {
    Tcl_Size Tcl_WriteObj(Tcl_Channel chan, Tcl_Obj *objPtr)
}
declare 340 {
    char *Tcl_GetString(Tcl_Obj *objPtr)
}








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
}
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)
#}
# 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)
}
declare 355 {
    unsigned short *Tcl_UtfToChar16DString(const char *src,
	    size_t 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)
}
declare 360 {
    int Tcl_ParseBraces(Tcl_Interp *interp, const char *start,
	    size_t 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)
}
declare 362 {
    int Tcl_ParseExpr(Tcl_Interp *interp, const char *start, size_t numBytes,
	    Tcl_Parse *parsePtr)
}
declare 363 {
    int Tcl_ParseQuotedString(Tcl_Interp *interp, const char *start,
	    size_t 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)
}
# 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)
}
declare 370 {
    int Tcl_UtfNcasecmp(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)
}
declare 377 {
    void Tcl_RegExpGetInfo(Tcl_RegExp regexp, Tcl_RegExpInfo *infoPtr)
}
declare 378 {
    Tcl_Obj *Tcl_NewUnicodeObj(const Tcl_UniChar *unicode, size_t numChars)
}
declare 379 {
    void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode,
	    size_t numChars)
}
declare 380 {
    size_t Tcl_GetCharLength(Tcl_Obj *objPtr)
}
declare 381 {
    int Tcl_GetUniChar(Tcl_Obj *objPtr, size_t 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)
}
# Removed in 9.0
#declare 384 {
#    void Tcl_AppendUnicodeToObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode,
#	    size_t length)
#}

declare 385 {
    int Tcl_RegExpMatchObj(Tcl_Interp *interp, Tcl_Obj *textObj,
	    Tcl_Obj *patternObj)
}
declare 386 {
    void Tcl_SetNotifier(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[])
}
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)
}

# Introduced in 8.3.2
declare 394 {
    size_t Tcl_ReadRaw(Tcl_Channel chan, char *dst, size_t bytesToRead)
}
declare 395 {
    size_t Tcl_WriteRaw(Tcl_Channel chan, const char *src, size_t 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)







<
|
|
<
<
<
<
<
<
>


|



|





<
<
<
<
<





|



|




|


|
|



|




|
















|


|


















|





|



|


|


|

<
<
<
<

|

<
|
|
|
<
>





|












|









|




|


|


















<
<
<
<
<












<
<
<
<
<







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
}
declare 350 {
    int Tcl_UniCharIsUpper(int ch)
}
declare 351 {
    int Tcl_UniCharIsWordChar(int ch)
}

declare 352 {
    Tcl_Size Tcl_Char16Len(const unsigned short *uniStr)






}
declare 354 {
    char *Tcl_Char16ToUtfDString(const unsigned short *uniStr,
	    Tcl_Size uniLength, Tcl_DString *dsPtr)
}
declare 355 {
    unsigned short *Tcl_UtfToChar16DString(const char *src,
	    Tcl_Size length, Tcl_DString *dsPtr)
}
declare 356 {
    Tcl_RegExp Tcl_GetRegExpFromObj(Tcl_Interp *interp, Tcl_Obj *patObj,
	    int flags)
}





declare 358 {
    void Tcl_FreeParse(Tcl_Parse *parsePtr)
}
declare 359 {
    void Tcl_LogCommandInfo(Tcl_Interp *interp, const char *script,
	    const char *command, Tcl_Size length)
}
declare 360 {
    int Tcl_ParseBraces(Tcl_Interp *interp, const char *start,
	    Tcl_Size numBytes, Tcl_Parse *parsePtr, int append,
	    const char **termPtr)
}
declare 361 {
    int Tcl_ParseCommand(Tcl_Interp *interp, const char *start,
	    Tcl_Size numBytes, int nested, Tcl_Parse *parsePtr)
}
declare 362 {
    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,
	    Tcl_Size numBytes, Tcl_Parse *parsePtr, int append,
	    const char **termPtr)
}
declare 364 {
    int Tcl_ParseVarName(Tcl_Interp *interp, const char *start,
	    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 TclUtfNcmp(const char *s1, const char *s2, size_t n)
}
declare 370 {
    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, 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, Tcl_Size numChars)
}
declare 379 {
    void Tcl_SetUnicodeObj(Tcl_Obj *objPtr, const Tcl_UniChar *unicode,
	    Tcl_Size numChars)
}
declare 380 {
    Tcl_Size TclGetCharLength(Tcl_Obj *objPtr)
}
declare 381 {
    int TclGetUniChar(Tcl_Obj *objPtr, Tcl_Size index)
}




declare 383 {
    Tcl_Obj *TclGetRange(Tcl_Obj *objPtr, Tcl_Size first, Tcl_Size last)
}

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(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,
	    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, TCL_HASH_TYPE stackSize, int flags)
}

# Introduced in 8.3.2
declare 394 {
    Tcl_Size Tcl_ReadRaw(Tcl_Channel chan, char *dst, Tcl_Size bytesToRead)
}
declare 395 {
    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)
}





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)
}





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
}
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)
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1302
1303
1304
1305
1306
1307
1308



















1309
1310
1311
1312
1313
1314
1315
}
declare 417 {
    void Tcl_ClearChannelHandlers(Tcl_Channel channel)
}
declare 418 {
    int Tcl_IsChannelExisting(const char *channelName)
}



















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
	    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)
}
declare 429 {
    void *Tcl_AttemptDbCkalloc(size_t size, const char *file, int line)
}
declare 430 {
    void *Tcl_AttemptRealloc(void *ptr, size_t size)
}
declare 431 {
    void *Tcl_AttemptDbCkrealloc(void *ptr, size_t size,
	    const char *file, int line)
}
declare 432 {
    int Tcl_AttemptSetObjLength(Tcl_Obj *objPtr, size_t 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)
}

# 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







|


|


|


|



|









|

<
<
<
<
<
<
<
<
<
<
<
<







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
	    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(TCL_HASH_TYPE size)
}
declare 429 {
    void *Tcl_AttemptDbCkalloc(TCL_HASH_TYPE size, const char *file, int line)
}
declare 430 {
    void *Tcl_AttemptRealloc(void *ptr, TCL_HASH_TYPE size)
}
declare 431 {
    void *Tcl_AttemptDbCkrealloc(void *ptr, TCL_HASH_TYPE size,
	    const char *file, int line)
}
declare 432 {
    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 *TclGetUnicodeFromObj(Tcl_Obj *objPtr, void *lengthPtr)
}













# 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
    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,
	    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 {







|
|







1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
    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_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
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)
}
declare 461 {
    Tcl_Obj *Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *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 *const objv[])
}
declare 465 {
    void *Tcl_FSGetInternalRep(Tcl_Obj *pathPtr,
	    const Tcl_Filesystem *fsPtr)
}
declare 466 {







|


|








|







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
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, Tcl_Size elements)
}
declare 461 {
    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, 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
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)
}

# 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_CmdObjTraceProc *objProc, void *clientData,
	    Tcl_CmdObjTraceDeleteProc *delProc)
}
declare 484 {
    int Tcl_GetCommandInfoFromToken(Tcl_Command token, Tcl_CmdInfo *infoPtr)
}
declare 485 {







|









|







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
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,
	    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, 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
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)
}
declare 492 {
    Tcl_WideInt Tcl_Tell(Tcl_Channel chan)
}

# TIP#91 (back-compat enhancements for channels) dkf
declare 493 {
    Tcl_DriverWideSeekProc *Tcl_ChannelWideSeekProc(
	    const Tcl_ChannelType *chanTypePtr)
}







|


|







1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
declare 489 {
    void Tcl_SetWideIntObj(Tcl_Obj *objPtr, Tcl_WideInt wideValue)
}
declare 490 {
    Tcl_StatBuf *Tcl_AllocStatBuf(void)
}
declare 491 {
    long long Tcl_Seek(Tcl_Channel chan, long long offset, int mode)
}
declare 492 {
    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
	    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)
}
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)
}
declare 502 {
    int Tcl_DictObjRemoveKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr,
	    int keyc, Tcl_Obj *const *keyv)
}
declare 503 {
    Tcl_Obj *Tcl_NewDictObj(void)
}
declare 504 {
    Tcl_Obj *Tcl_DbNewDictObj(const char *file, int line)
}







|















|



|







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
	    Tcl_Obj **valuePtrPtr)
}
declare 496 {
    int Tcl_DictObjRemove(Tcl_Interp *interp, Tcl_Obj *dictPtr,
	    Tcl_Obj *keyPtr)
}
declare 497 {
    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,
	    Tcl_Size keyc, Tcl_Obj *const *keyv, Tcl_Obj *valuePtr)
}
declare 502 {
    int Tcl_DictObjRemoveKeyList(Tcl_Interp *interp, Tcl_Obj *dictPtr,
	    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

# 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)
}
declare 526 {
    void Tcl_LimitSetTime(Tcl_Interp *interp, Tcl_Time *timeLimitPtr)
}
declare 527 {
    void Tcl_LimitSetGranularity(Tcl_Interp *interp, int type, int granularity)
}







<
<
<
<
<




















|







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

# TIP#137 (encoding-aware source command) dgp for Anton Kovalenko
declare 518 {
    int Tcl_FSEvalFileEx(Tcl_Interp *interp, Tcl_Obj *fileName,
	    const char *encodingName)
}






# 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, 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
}
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)
}
declare 561 {
    Tcl_DriverTruncateProc *Tcl_ChannelTruncateProc(
	    const Tcl_ChannelType *chanTypePtr)
}

# TIP#219 (channel reflection api) akupries







|







1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
}
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, 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
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)
}

# 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)
}
declare 576 {
    Tcl_Obj *Tcl_Format(Tcl_Interp *interp, const char *format, int 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[])
}
declare 578 {
    Tcl_Obj *Tcl_ObjPrintf(const char *format, ...)
}
declare 579 {
    void Tcl_AppendPrintfToObj(Tcl_Obj *objPtr, const char *format, ...)
}







|








|


|




|







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
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,
	    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,
	    Tcl_Size length, Tcl_Size limit, const char *ellipsis)
}
declare 576 {
    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, 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
	    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,
	    Tcl_Obj *const objv[], int flags)
}
declare 586 {
    int Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd, int 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[])
}

# TIP#316 (Tcl_StatBuf reader functions) dkf
declare 589 {
    unsigned Tcl_GetFSDeviceFromStat(const Tcl_StatBuf *statPtr)
}
declare 590 {







|



|











|







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
	    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, Tcl_Size objc,
	    Tcl_Obj *const objv[], int flags)
}
declare 586 {
    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, 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
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)
}
declare 597 {
    Tcl_WideInt Tcl_GetModificationTimeFromStat(const Tcl_StatBuf *statPtr)
}
declare 598 {
    Tcl_WideInt Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr)
}
declare 599 {
    Tcl_WideUInt Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr)
}
declare 600 {
    Tcl_WideUInt 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)
}

# TIP#336 (manipulate the error line) dgp
declare 605 {
    int Tcl_GetErrorLine(Tcl_Interp *interp)
}
declare 606 {







|


|


|


|


|

















|
|







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
declare 594 {
    int Tcl_GetGroupIdFromStat(const Tcl_StatBuf *statPtr)
}
declare 595 {
    int Tcl_GetDeviceTypeFromStat(const Tcl_StatBuf *statPtr)
}
declare 596 {
    long long Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr)
}
declare 597 {
    long long Tcl_GetModificationTimeFromStat(const Tcl_StatBuf *statPtr)
}
declare 598 {
    long long Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr)
}
declare 599 {
    unsigned long long Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr)
}
declare 600 {
    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 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
# 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)
}
declare 612 {
    unsigned int Tcl_ZlibCRC32(unsigned int crc, const unsigned char *buf,
	    size_t len)
}
declare 613 {
    unsigned int Tcl_ZlibAdler32(unsigned int adler, const unsigned char *buf,
	    size_t 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)
}
declare 620 {
    int Tcl_ZlibStreamClose(Tcl_ZlibStream zshandle)
}
declare 621 {
    int Tcl_ZlibStreamReset(Tcl_ZlibStream zshandle)
}







|



|



|



















|







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
# 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,
	    Tcl_Size buffersize, Tcl_Obj *gzipHeaderDictObj)
}
declare 612 {
    unsigned int Tcl_ZlibCRC32(unsigned int crc, const unsigned char *buf,
	    Tcl_Size len)
}
declare 613 {
    unsigned int Tcl_ZlibAdler32(unsigned int adler, const unsigned char *buf,
	    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,
	    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
declare 630 {
    void Tcl_ZlibStreamSetCompressionDictionary(Tcl_ZlibStream zhandle,
	    Tcl_Obj *compressionDictionaryObj)
}

# ----- BASELINE -- FOR -- 8.6.0 ----- #

# TIP #456
declare 631 {
    Tcl_Channel Tcl_OpenTcpServerEx(Tcl_Interp *interp, const char *service,
	    const char *host, unsigned int flags, Tcl_TcpAcceptProc *acceptProc,
	    void *callbackData)
}

# TIP #430
declare 632 {
    int TclZipfs_Mount(Tcl_Interp *interp, const char *mountPoint,
	    const char *zipname, 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)
}

# TIP #445
declare 636 {
    void Tcl_FreeIntRep(Tcl_Obj *objPtr)
}
declare 637 {
    char *Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes,
	    size_t numBytes)
}
declare 638 {
    Tcl_ObjIntRep *Tcl_FetchIntRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr)
}
declare 639 {
    void Tcl_StoreIntRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr,
	    const Tcl_ObjIntRep *irPtr)
}
declare 640 {
    int Tcl_HasStringRep(Tcl_Obj *objPtr)
}

# TIP #506
declare 641 {







|


|
|




|
|








|
|




|



|


|


|
|







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
declare 630 {
    void Tcl_ZlibStreamSetCompressionDictionary(Tcl_ZlibStream zhandle,
	    Tcl_Obj *compressionDictionaryObj)
}

# ----- BASELINE -- FOR -- 8.6.0 ----- #

# TIP #456/#468
declare 631 {
    Tcl_Channel Tcl_OpenTcpServerEx(Tcl_Interp *interp, const char *service,
	    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 *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 void *data,
	    size_t datalen, const char *mountPoint, int copy)
}

# TIP #445
declare 636 {
    void Tcl_FreeInternalRep(Tcl_Obj *objPtr)
}
declare 637 {
    char *Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes,
	    TCL_HASH_TYPE numBytes)
}
declare 638 {
    Tcl_ObjInternalRep *Tcl_FetchInternalRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr)
}
declare 639 {
    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
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)
}

declare 645 {
    int Tcl_GetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    size_t endValue, size_t *indexPtr)
}

# TIP #548
declare 646 {
    int Tcl_UtfToUniChar(const char *src, int *chPtr)
}
declare 647 {
    char *Tcl_UniCharToUtfDString(const int *uniStr,
	    size_t uniLength, Tcl_DString *dsPtr)
}
declare 648 {
    int *Tcl_UtfToUniCharDString(const char *src,
	    size_t length, Tcl_DString *dsPtr)







































































































































































}

# ----- BASELINE -- FOR -- 8.7.0 ----- #





##############################################################################

# 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

# 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 win {
#    char *Tcl_WinTCharToUtf(const TCHAR *str, size_t len, Tcl_DString *dsPtr)
#}


################################
# Mac OS X 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,
	    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)
}
export {
    void Tcl_StaticPackage(Tcl_Interp *interp, const char *pkgName,
	    Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc)
}
export {
    void Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc)
}
export {
    Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc)
}
export {
    void 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)
}





# Local Variables:
# mode: tcl
# End:







|




|




|



|



|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
>
>
>
>













|

|
>
>
>
|
|
|
<
<
<
<
|
>

|
<
<
<
<
<
<
<
|
|
<
<







|



|
|


|





|

















|

>
>
>
>




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
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, Tcl_Size size)
}

declare 645 {
    int Tcl_GetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    Tcl_Size endValue, Tcl_Size *indexPtr)
}

# TIP #548
declare 646 {
    Tcl_Size Tcl_UtfToUniChar(const char *src, int *chPtr)
}
declare 647 {
    char *Tcl_UniCharToUtfDString(const int *uniStr,
	    Tcl_Size uniLength, Tcl_DString *dsPtr)
}
declare 648 {
    int *Tcl_UtfToUniCharDString(const char *src,
	    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 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)
}

# ----- BASELINE -- FOR -- 8.7.0 / 9.0.0 ----- #

declare 688 {
    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)

################################
# Mac OS X specific functions

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)




}

################################
# Windows specific functions







declare 3 {
    void Tcl_WinConvertError(unsigned errCode)


}

##############################################################################

# Public functions that are not accessible via the stubs table.

export {
    void Tcl_MainEx(Tcl_Size argc, char **argv, Tcl_AppInitProc *appInitProc,
    Tcl_Interp *interp)
}
export {
    void Tcl_StaticLibrary(Tcl_Interp *interp, const char *prefix,
	    Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc)
}
export {
    const char *Tcl_SetPanicProc(TCL_NORETURN1 Tcl_PanicProc *panicProc)
}
export {
    Tcl_ExitProc *Tcl_SetExitProc(TCL_NORETURN1 Tcl_ExitProc *proc)
}
export {
    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 {
    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
 * 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)
 * 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)
 */


#define TCL_MAJOR_VERSION   9


#define TCL_MINOR_VERSION   0
#define TCL_RELEASE_LEVEL   TCL_ALPHA_RELEASE
#define TCL_RELEASE_SERIAL  2

#define TCL_VERSION	    "9.0"
#define TCL_PATCH_LEVEL	    "9.0a2"


#if defined(RC_INVOKED)
/*
 * Utility macros: STRINGIFY takes an argument and wraps it in "" (double
 * quotation marks), JOIN joins two arguments.
 */








|



<


>
|
>
>
|
|
|

|
|
>







37
38
39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 * 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.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)

 */

#if !defined(TCL_MAJOR_VERSION)
#   define TCL_MAJOR_VERSION   9
#endif
#if TCL_MAJOR_VERSION == 9
#   define TCL_MINOR_VERSION   0
#   define TCL_RELEASE_LEVEL   TCL_BETA_RELEASE
#   define TCL_RELEASE_SERIAL  2

#   define TCL_VERSION	    "9.0"
#   define TCL_PATCH_LEVEL	    "9.0b2"
#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.
 */

96
97
98
99
100
101
102

103
104



105

106
107
108
109
110
111
112
113
114
115
116
117
118
 * 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>


#if defined(__GNUC__) && (__GNUC__ > 2)



#   define TCL_FORMAT_PRINTF(a,b) __attribute__ ((__format__ (__printf__, a, b)))

#   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)
#	define TCL_NOINLINE __declspec(noinline)
#   else
#	define TCL_NORETURN /* nothing */
#	define TCL_NOINLINE /* nothing */
#   endif
#   define TCL_NORETURN1 /* nothing */







>


>
>
>
|
>





|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
 * 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)))
#   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)
#	define TCL_NORETURN _declspec(noreturn)
#	define TCL_NOINLINE __declspec(noinline)
#   else
#	define TCL_NORETURN /* nothing */
#	define TCL_NOINLINE /* nothing */
#   endif
#   define TCL_NORETURN1 /* nothing */
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
 *
 * 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 STATIC_BUILD
#       define DLLIMPORT
#       define DLLEXPORT
#       ifdef _DLL
#           define CRTIMPORT __declspec(dllimport)
#       else
#           define CRTIMPORT







<
|







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.
 */


#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
/*
 * 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__ */








/*
 * 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(_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
#      endif
#   endif /* _WIN32 */
#endif /* !TCL_WIDE_INT_TYPE & !TCL_WIDE_INT_IS_LONG */

#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



#   define TCL_LL_MODIFIER	"ll"

#endif /* !TCL_LL_MODIFIER */
#ifndef TCL_Z_MODIFIER
#   if defined(__GNUC__) && !defined(_WIN32)
#	define TCL_Z_MODIFIER	"z"


#   else
#	define TCL_Z_MODIFIER	""
#   endif
#endif /* !TCL_Z_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 defined(_WIN32)

    typedef struct __stat64 Tcl_StatBuf;





#elif defined(__CYGWIN__)
    typedef struct {
	dev_t 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;
	/* 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;
    } 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
 * 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_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;







<



<





>
>
>
>
>
>
>
















<
<
<
<


|
<
<
<
<
<
<
<
<
<




|
|
|
<
|
|









>
>
>
|
>




>
>




>
>
>
>
>
>
>
>
>
>





>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>


|






|


|
|
|

<
<







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<


<
<









>







235
236
237
238
239
240
241

242
243
244

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272




273
274
275









276
277
278
279
280
281
282

283
284
285
286
287
288
289
290
291
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__

#	define TCL_WIDE_INT_IS_LONG 1
#	define TCL_CFG_DO64BIT 1
#    else /* !__LP64__ */

#	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))




 */

#if !defined(TCL_WIDE_INT_TYPE) && !defined(TCL_WIDE_INT_IS_LONG) && !defined(_WIN32) && !defined(__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

#   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"
#   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 */

#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 {
	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 */
	unsigned st_rdev;
	/* Here is a 4-byte gap */
	long long st_size;
	struct {long tv_sec;} st_atim;
	struct {long tv_sec;} st_mtim;
	struct {long tv_sec;} st_ctim;
    } Tcl_StatBuf;


#else
    typedef struct stat Tcl_StatBuf;
#endif

/*
 *----------------------------------------------------------------------------
 * Data structures defined opaquely in this module. The definitions below just
 * provide dummy types.














 */



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;
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
/*
 * 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 {

    size_t start;			/* Character offset of first character in
				 * match. */
    size_t end;			/* Character offset of first character after
				 * the match. */




} Tcl_RegExpIndices;

typedef struct Tcl_RegExpInfo {
    size_t nsubs;			/* Number of subexpressions in the compiled
				 * expression. */
    Tcl_RegExpIndices *matches;	/* Array of nsubs match offset pairs. */

    size_t extendStart;		/* The offset at which a subsequent match
				 * might begin. */




} Tcl_RegExpInfo;

/*
 * Picky compilers complain if this typdef doesn't appear before the struct's
 * reference in tclDecls.h.
 */








>
|

|

>
>
>
>



|


>
|

>
>
>
>







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
/*
 * 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
    Tcl_Size start;			/* Character offset of first character in
				 * match. */
    Tcl_Size end;			/* Character offset of first character after
				 * the match. */
#else
    long start;
    long end;
#endif
} Tcl_RegExpIndices;

typedef struct Tcl_RegExpInfo {
    Tcl_Size nsubs;			/* Number of subexpressions in the compiled
				 * expression. */
    Tcl_RegExpIndices *matches;	/* Array of nsubs match offset pairs. */
#if TCL_MAJOR_VERSION > 8
    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.
 */

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
	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 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_FileProc) (void *clientData, int mask);
#define Tcl_FileFreeProc Tcl_FreeProc
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);
















typedef int (Tcl_PackageInitProc) (Tcl_Interp *interp);
typedef int (Tcl_PackageUnloadProc) (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);




























/*
 *----------------------------------------------------------------------------
 * 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.
 */








|




|

|

<






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|


















|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	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);
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);
typedef void (Tcl_ExitProc) (void *clientData);
typedef void (Tcl_FileProc) (void *clientData, int mask);
typedef void (Tcl_FileFreeProc) (void *clientData);
typedef void (Tcl_FreeInternalRepProc) (struct Tcl_Obj *objPtr);

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_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
    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. */






















} Tcl_ObjType;












/*
 * The following structure stores an internal representation (intrep) for
 * a Tcl value. An intrep 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.
 */

typedef union Tcl_ObjIntRep {	/* 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;

/*
 * 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. */
    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
				 * 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_ObjIntRep internalRep;	/* 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).
 */








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>

|
|

|


|













|








|











|





|



<
<
<
<
<
<
<
<







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
    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;

    /* List emulation functions - ObjType Version 1 */
    Tcl_ObjTypeLengthProc *lengthProc;	     /* Return the [llength] of the
					     ** AbstractList */
    Tcl_ObjTypeIndexProc *indexProc;	     /* Return a value (Tcl_Obj) for
					     ** [lindex $al $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 indicie
					     ** with the given valueObj. */
    Tcl_ObjTypeReplaceProc *replaceProc;     /* Replace subset with subset */
    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 */
#endif

/*
 * 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 internalrep.
 */

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_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 {
    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. */
    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;	/* The internal representation: */
} Tcl_Obj;










/*
 *----------------------------------------------------------------------------
 * 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).
 */

710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
 * 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;
    int dummy1;
    int dummy2;
    void *dummy3;
    void *dummy4;
    void *dummy5;
    int dummy6;
    void *dummy7;
    void *dummy8;
    int dummy9;
    void *dummy10;
    void *dummy11;
    void *dummy12;
    void *dummy13;
} Tcl_CallFrame;

/*







|



|


|







800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
 * 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;
    int dummy1;
    Tcl_Size dummy2;
    void *dummy3;
    void *dummy4;
    void *dummy5;
    Tcl_Size dummy6;
    void *dummy7;
    void *dummy8;
    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
 * 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 {
    int isNativeObjectProc;	/* 1 if objProc was registered by a call to
				 * Tcl_CreateObjCommand; 0 otherwise.

				 * Tcl_SetCmdInfo does not modify this
				 * 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. */
    Tcl_CmdDeleteProc *deleteProc;
				/* Function to call when command is
				 * deleted. */
    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_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
				 * 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)







|

|
>
|
<














>
>













|
|
|







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
 * 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 {
    int isNativeObjectProc;	/* 1 if objProc was registered by a call to
				 * Tcl_CreateObjCommand; 2 if objProc was registered by
				 * a call to Tcl_CreateObjCommand2; 0 otherwise.
				 * Tcl_SetCmdInfo does not modify this 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. */
    Tcl_CmdDeleteProc *deleteProc;
				/* Function to call when command is
				 * deleted. */
    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. */
    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

/*
 * 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















/*
 * 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_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_INDEX_TEMP_TABLE	2











/*
 *----------------------------------------------------------------------------
 * 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:







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















>
>





>
|

>
>
>
>
>
>
>
>
>
>







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

/*
 * 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	(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	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:
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
#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.
 */







<
<
<
<







997
998
999
1000
1001
1002
1003




1004
1005
1006
1007
1008
1009
1010
#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




/* 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
#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

#  define TCL_HASH_TYPE size_t



#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);







<


<
<
<
<





|






>

>
>
>







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
#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

#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)




#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);
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
 */

struct Tcl_HashEntry {
    Tcl_HashEntry *nextPtr;	/* Pointer to next entry in this hash bucket,
				 * or NULL for end of chain. */
    Tcl_HashTable *tablePtr;	/* Pointer to table containing entry. */
    size_t hash;		/* Hash value. */
    void *clientData;		/* Application stores something here with
				 * Tcl_SetHashValue. */
    union {			/* Key has one of these forms: */
	char *oneWordValue;	/* One-word value for key. */
	Tcl_Obj *objPtr;	/* Tcl_Obj * key value. */
	int words[1];		/* Multiple integer words for key. The actual
				 * size will be as large as necessary for this
				 * table's keys. */







|







1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
 */

struct Tcl_HashEntry {
    Tcl_HashEntry *nextPtr;	/* Pointer to next entry in this hash bucket,
				 * or NULL for end of chain. */
    Tcl_HashTable *tablePtr;	/* Pointer to table containing entry. */
    size_t hash;		/* Hash value. */
    void *clientData;	/* Application stores something here with
				 * Tcl_SetHashValue. */
    union {			/* Key has one of these forms: */
	char *oneWordValue;	/* One-word value for key. */
	Tcl_Obj *objPtr;	/* Tcl_Obj * key value. */
	int words[1];		/* Multiple integer words for key. The actual
				 * size will be as large as necessary for this
				 * table's keys. */
985
986
987
988
989
990
991







992
993
994
995

996
997
998
999
1000
1001
1002
 *				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.







 */

#define TCL_HASH_KEY_RANDOMIZE_HASH 0x1
#define TCL_HASH_KEY_SYSTEM_HASH    0x2


/*
 * Structure definition for the methods associated with a hash table key type.
 */

#define TCL_HASH_KEY_TYPE_VERSION 1
struct Tcl_HashKeyType {







>
>
>
>
>
>
>




>







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
 *				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
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
				 * **bucketPtr. */
    size_t numEntries;		/* Total number of entries present in
				 * table. */
    size_t rebuildSize;		/* Enlarge table when numEntries gets to be
				 * this large. */

    size_t mask;		/* Mask value used in hashing function. */

    int downShift;		/* Shift count used in hashing function.
				 * Designed to use high-order bits of
				 * randomized keys. */



    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
				 * present one. */
    Tcl_HashEntry *nextEntryPtr;/* Next entry to be enumerated in the current
				 * bucket. */
} Tcl_HashSearch;

/*
 * Acceptable key types for hash tables:







|

|

|

>

>



>
>
>




















|







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
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). */
    Tcl_Size numBuckets;		/* Total number of buckets allocated at
				 * **bucketPtr. */
    Tcl_Size numEntries;		/* Total number of entries present in
				 * table. */
    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. */
    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
 * 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,
				 * 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







|







1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
 * dictionaries. These fields should not be accessed by code outside
 * tclDictObj.c
 */

typedef struct {
    void *next;			/* Search position for underlying hash
				 * table. */
    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

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:
 */

typedef enum {
    TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK

} 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 {



    long sec;			/* Seconds. */




    long usec;			/* Microseconds. */

} Tcl_Time;

typedef void (Tcl_SetTimerProc) (const Tcl_Time *timePtr);
typedef int (Tcl_WaitForEventProc) (const Tcl_Time *timePtr);

/*
 * TIP #233 (Virtualized Time)







|



|
>

















>
>
>

>
>
>
>

>







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

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/Tcl_ThreadQueueEvent:
 */

typedef enum {
    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
#define TCL_CLOSE_WRITE		(1<<2)

/*
 * Value to use as the closeProc for a channel that supports the close2Proc
 * interface.
 */


#define TCL_CLOSE2PROC		NULL




/*
 * Channel version tag. This was introduced in 8.3.2/8.4.
 */

#define TCL_CHANNEL_VERSION_5	((Tcl_ChannelTypeVersion) 0x5)








>
|
>
>
>







1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
#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
#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
			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);
/*
 * 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);

/*
 * 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;
				/* 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;
				/* 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. */







|
|









|


















|
<




|
<







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
			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 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,
			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;		/* 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;		/* 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
 * 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
				 * 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;







|







1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
 * 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. */
    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;
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
 * 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,
				 * this field tells how many of them there are
				 * (including components of components, etc.).
				 * The component tokens immediately follow
				 * this one. */
} Tcl_Token;

/*







|
|







1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
 * 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. */
    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
 *				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
 *				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







|







1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
 *				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 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
 */

#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
				 * 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
				 * character of first word, up through the
				 * terminating newline, close bracket, or
				 * semicolon. */
    int 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
				 * *tokenPtr. */
    int errorType;		/* One of the parsing error types defined
				 * above. */







    /*
     * 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). */

    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. */
    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;







|





|



|






|
|



>
>
>
>
>
>


















>
|
<
<
|







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
 */

#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. */
    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. */
    Tcl_Size commandSize;		/* Number of bytes in command, including first
				 * character of first word, up through the
				 * terminating newline, close bracket, or
				 * semicolon. */
    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. */
    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;


#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;
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
				/* Function to convert from UTF-8 into
				 * external encoding. */
    Tcl_FreeProc *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 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. */
} 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







|



|







1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
				/* Function to convert from UTF-8 into
				 * external encoding. */
    Tcl_FreeProc *freeProc;
				/* If non-NULL, function to call when this
				 * encoding is deleted. */
    void *clientData;	/* Arbitrary value associated with encoding
				 * type. Passed to conversion functions. */
    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, 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
 *				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
 *				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
 *				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.






 */

#define TCL_ENCODING_START		0x01
#define TCL_ENCODING_END		0x02



#define TCL_ENCODING_STOPONERROR	0x04

#define TCL_ENCODING_NO_TERMINATE	0x08
#define TCL_ENCODING_CHAR_LIMIT		0x10











/*
 * 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
 *				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
 *				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
 * (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

#define TCL_UTF_MAX		4



#endif

/*
 * This represents a Unicode character. Any changes to this should also be
 * reflected in regcustom.h.
 */

#if TCL_UTF_MAX > 3
    /*
     * int isn't 100% accurate as it should be a strict 4-byte value
     * (perhaps wchar_t). ILP64/SILP64 systems may have troubles. The
     * size of this value must be reflected correctly in regcustom.h.
     */
typedef int Tcl_UniChar;
#else
typedef unsigned short Tcl_UniChar;


#endif

/*
 *----------------------------------------------------------------------------
 * TIP #59: The following structure is used in calls 'Tcl_RegisterConfig' to
 * provide the system with the embedded configuration data.
 */







|
<
<
<
<
<
<
<














>
>
>
>
>
>




>
>
>
|
>


>
>
>
>
>
>
>
>
>
>




















|
<
<


|
<









|
<






>
|
>
>
>







|


|



|

>
>







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
 *				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 -	Not used any more.







 * 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
#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.


 * TCL_CONVERT_UNKNOWN -	The source string contained a character that
 *				could not be represented in the target
 *				encoding.

 */

#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. 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
#   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 == 4
    /*
     * int isn't 100% accurate as it should be a strict 4-byte value
     * (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;
#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

/*
 * 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);



typedef void (Tcl_LimitHandlerDeleteProc) (void *clientData);


#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







>
>
>

>







2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145

/*
 * 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
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
/*
 * 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);

/*
 * Shorthand for commonly used argTable entries.
 */

#define TCL_ARGV_AUTO_HELP \
    {TCL_ARGV_HELP,	"-help",	NULL,	NULL, \







|
|







2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
/*
 * 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 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
 *----------------------------------------------------------------------------
 * 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
 */

#define TCL_IO_FAILURE	((size_t)-1)
#define TCL_AUTO_LENGTH	((size_t)-1)
#define TCL_INDEX_NONE  ((size_t)-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.
 */


#define TCL_STUB_MAGIC		((int) 0xFCA3BACB + (int) sizeof(void *))




/*
 * 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);


#if defined(_WIN32)
    TCL_NORETURN1 void Tcl_ConsolePanic(const char *format, ...);
#else
#   define Tcl_ConsolePanic NULL
#endif

#ifdef USE_TCL_STUBS












#if 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_STUB_MAGIC)
#endif
#else


#if 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,
			    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 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);
#ifdef _WIN32
EXTERN int		TclZipfs_AppHook(int *argc, wchar_t ***argv);
#else
EXTERN int		TclZipfs_AppHook(int *argc, char ***argv);



































#endif

/*
 *----------------------------------------------------------------------------
 * Include the public function declarations that are accessible via the stubs
 * table.
 */







|


|
|
|















>
|
>
>
>












>
>







>
>
>
>
>
>
>
>
>
>
>
>
|











>
>
|
















|
|



|

|
>
|

|
|
|
|
>
>
>


|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *----------------------------------------------------------------------------
 * Definitions needed for the Tcl_OpenTcpServerEx function. [TIP #456]
 */
#define TCL_TCPSERVER_REUSEADDR (1<<0)
#define TCL_TCPSERVER_REUSEPORT (1<<1)

/*
 * Constants for special Tcl_Size-typed values, see TIP #494
 */

#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 *))
#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, ...);
#else
#   define Tcl_ConsolePanic 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.7.0", \
	    (exact)|(TCL_MAJOR_VERSION<<8)|(0xFF<<16), \
	    TCL_STUB_MAGIC)
# endif
#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_STUB_MAGIC)
#endif
#else
#if TCL_MAJOR_VERSION < 9
#   error "Please define -DUSE_TCL_STUBS"
#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(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 const char *	Tcl_InitSubsystems(void);
EXTERN void		Tcl_GetMemoryInfo(Tcl_DString *dsPtr);
EXTERN const char *	Tcl_FindExecutable(const char *argv0);
EXTERN const char *	Tcl_SetPreInitScript(const char *string);
EXTERN const char *	Tcl_SetPanicProc(
			    TCL_NORETURN1 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_NORETURN1 Tcl_ExitProc *proc);
#ifdef _WIN32
EXTERN const char *TclZipfs_AppHook(int *argc, wchar_t ***argv);
#else
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
 */

#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))
#   else
#	define ckfree Tcl_Free
#	define ckrealloc Tcl_Realloc
#	define attemptckrealloc Tcl_AttemptRealloc
#   endif
#endif








|
|
|







2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
 */

#ifndef BUILD_tcl
#   define ckalloc Tcl_Alloc
#   define attemptckalloc Tcl_AttemptAlloc
#   ifdef _MSC_VER
	/* Silence invalid C4090 warnings */
#	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
	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__)



















#else
#   undef Tcl_IncrRefCount
#   define Tcl_IncrRefCount(objPtr) \
	++(objPtr)->refCount
    /*
     * Use do/while0 idiom for optimum correctness without compiler warnings.
     * http://c2.com/cgi/wiki?TrivialDoWhileLoop
     */
#   undef Tcl_DecrRefCount
#   define Tcl_DecrRefCount(objPtr) \
	do { \
	    Tcl_Obj *_objPtr = (objPtr); \
	    if (_objPtr->refCount-- <= 1) { \
		TclFreeObj(_objPtr); \
	    } \
	} while(0)
#   undef Tcl_IsShared
#   define Tcl_IsShared(objPtr) \
	((objPtr)->refCount > 1)


















#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.
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|


|












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	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) \
	((void)++(objPtr)->refCount)
    /*
     * Use do/while0 idiom for optimum correctness without compiler warnings.
     * https://wiki.c2.com/?TrivialDoWhileLoop
     */
#   undef Tcl_DecrRefCount
#   define Tcl_DecrRefCount(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 release the obj if there is no referece count,
 * otherwise let it be.
 */
#   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

/*
 *----------------------------------------------------------------------------
 * 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_GetHashKey(tablePtr, h) \
	((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:
 */


#define Tcl_FindHashEntry(tablePtr, key) \
	(*((tablePtr)->findProc))(tablePtr, (const char *)(key))

#define Tcl_CreateHashEntry(tablePtr, key, newPtr) \
	(*((tablePtr)->createProc))(tablePtr, (const char *)(key), newPtr)

#endif /* RC_INVOKED */

/*
 * end block for C++







|











>


>







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

/*
 *----------------------------------------------------------------------------
 * 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_GetHashKey(tablePtr, h) \
	((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
/*
 * 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.
 *
 * 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.
 */









|
|
|







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 © 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
#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__)
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







|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#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__)
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
 * 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	((sizeof(union overhead) + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1))
#define NBUCKETS	(13 - (MINBLOCK >> 4))
#define MAXMALLOC	(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.
 */







|







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
 * 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	((sizeof(union overhead) + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1))
#define NBUCKETS	(13 - (MINBLOCK >> 4))
#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
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
 * in Tcl, we make this module self-initializing after all with the allocInit
 * variable.
 */

#if TCL_THREADS
static Tcl_Mutex *allocMutexPtr;
#endif







|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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. 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
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpRealloc(
    void *oldPtr,		/* Pointer to alloced block. */
    size_t numBytes)	/* New size of memory. */
{
    int i;
    union overhead *overPtr;
    struct block *bigBlockPtr;
    int expensive;
    size_t maxSize;







|







506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpRealloc(
    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
	overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1);
	BLOCK_END(overPtr) = RMAGIC;
#endif

	Tcl_MutexUnlock(allocMutexPtr);
	return (void *)(overPtr+1);
    }
    maxSize = 1 << (i+3);
    expensive = 0;
    if (numBytes+OVERHEAD > maxSize) {
	expensive = 1;
    } else if (i>0 && numBytes+OVERHEAD < maxSize/2) {
	expensive = 1;
    }








|







578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
	overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1);
	BLOCK_END(overPtr) = RMAGIC;
#endif

	Tcl_MutexUnlock(allocMutexPtr);
	return (void *)(overPtr+1);
    }
    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
	}
	memcpy(newPtr, oldPtr, numBytes);
	TclpFree(oldPtr);
	return newPtr;
    }

    /*
     * Ok, we don't have to copy, it fits as-is
     */

#ifndef NDEBUG
    overPtr->realBlockSize = (numBytes + RSLOP - 1) & ~(RSLOP - 1);
    BLOCK_END(overPtr) = RMAGIC;
#endif








|







605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
	}
	memcpy(newPtr, oldPtr, numBytes);
	TclpFree(oldPtr);
	return newPtr;
    }

    /*
     * 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
    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));
    }

    fprintf(stderr, "\nused:\t");
    for (i = 0; i < NBUCKETS; i++) {
	fprintf(stderr, " %" TCL_Z_MODIFIER "u", numMallocs[i]);
	totalUsed += numMallocs[i] * (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",
	    MAXMALLOC, numMallocs[NBUCKETS]);

    Tcl_MutexUnlock(allocMutexPtr);
}
#endif

#else	/* !USE_TCLALLOC */







|





|




|







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
    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) * ((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] * ((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 (>%" TCL_Z_MODIFIER "u) blocks in use: %" TCL_Z_MODIFIER "u\n",
	    MAXMALLOC, numMallocs[NBUCKETS]);

    Tcl_MutexUnlock(allocMutexPtr);
}
#endif

#else	/* !USE_TCLALLOC */
745
746
747
748
749
750
751


752
753
754
755
756
757
758
759
760
    void *oldPtr,		/* Pointer to alloced block. */
    size_t numBytes)	/* New size of memory. */
{
    return realloc(oldPtr, numBytes);
}

#endif /* !USE_TCLALLOC */


#endif /* !TCL_THREADS */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>









745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
    void *oldPtr,		/* Pointer to alloced block. */
    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
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
/*
 * 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 void
assignNumber(
    int useDoubles,
    Tcl_WideInt *intNumberPtr,
    double *dblNumberPtr,
    Tcl_Obj *numberObj)
{
    void *clientData;
    int tcl_number_type;

    if (Tcl_GetNumberFromObj(NULL, numberObj, &clientData, &tcl_number_type) != TCL_OK
	    || tcl_number_type == TCL_NUMBER_BIG) {
	return;
    }
    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;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 * 	An empty Tcl_Obj if the range is invalid.
 *
 * Side Effects:
 *
 * 	None.
 *----------------------------------------------------------------------
 */

int
TclNewArithSeriesObj(
    Tcl_Interp *interp,       /* For error reporting */
    Tcl_Obj **arithSeriesObj, /* return value */
    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;

    if (startObj) {
	assignNumber(useDoubles, &start, &dstart, startObj);
    } else {
	start = 0;
	dstart = start;
    }
    if (stepObj) {
	assignNumber(useDoubles, &step, &dstep, stepObj);
	if (useDoubles) {
	    step = dstep;
	} else {
	    dstep = step;
	}
	if (dstep == 0) {
	    TclNewObj(*arithSeriesObj);
	    return TCL_OK;
	}
    }
    if (endObj) {
	assignNumber(useDoubles, &end, &dend, endObj);
    }
    if (lenObj) {
	if (TCL_OK != Tcl_GetWideIntFromObj(interp, lenObj, &len)) {
	    return TCL_ERROR;
	}
    }

    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", (void *)NULL);
	return TCL_ERROR;
    }

    if (arithSeriesObj) {
	*arithSeriesObj = (useDoubles)
	    ? NewArithSeriesDbl(dstart, dend, dstep, len)
	    : NewArithSeriesInt(start, end, step, len);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * 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)) {
	int status = TclNewArithSeriesObj(NULL, newObjPtr,
		arithSeriesRepPtr->isDouble, startObj, endObj, stepObj, NULL);

	Tcl_DecrRefCount(startObj);
	Tcl_DecrRefCount(endObj);
	Tcl_DecrRefCount(stepObj);
	return status;
    }

    /*
     * 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", (void *)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", (void *)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);
	if (TclNewArithSeriesObj(NULL, &resultObj, isDouble,
		startObj, endObj, stepObj, lenObj) != TCL_OK) {
	    resultObj = NULL;
	}
	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 TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
/*
 * 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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

/*-
 *- THINGS TO DO:








|
|







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 © 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:
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
				 * code */
    int* 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) */







|

|







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. */
    Tcl_Size cmdLine;	/* Current line number within the assembly
				 * code */
    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
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,
			    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**);







|







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 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
static Tcl_DupInternalRepProc	DupAssembleCodeInternalRep;

static const Tcl_ObjType assembleCodeType = {
    "assemblecode",
    FreeAssembleCodeInternalRep, /* freeIntRepProc */
    DupAssembleCodeInternalRep,	 /* dupIntRepProc */
    NULL,			 /* updateStringProc */
    NULL			 /* setFromAnyProc */

};

/*
 * Source instructions recognized in the Tcl Assembly Language (TAL)
 */

static const TalInstDesc TalInstructionTable[] = {







|
>







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 */
    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
 *	include whatever the code does.
 *
 *-----------------------------------------------------------------------------
 */

int
Tcl_AssembleObjCmd(
    ClientData 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_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. */







|














|







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(
    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(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
    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 */

    /*
     * Get the expression ByteCode from the object. If it exists, make sure it
     * is valid in the current context.
     */

    ByteCodeGetIntRep(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);
    }

    /*
     * Set up the compilation environment, and assemble the code.
     */

    source = TclGetStringFromObj(objPtr, &sourceLen);







|






|
















|







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 */
    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.
     */

    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_StoreInternalRep(objPtr, &assembleCodeType, NULL);
    }

    /*
     * Set up the compilation environment, and assemble the code.
     */

    source = TclGetStringFromObj(objPtr, &sourceLen);
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
    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;
    int offset = envPtr->codeNext - envPtr->codeStart;
    int 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;







|

|



















<







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
    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 */

    size_t numCommands = envPtr->numCommands;
    int offset = envPtr->codeNext - envPtr->codeStart;
    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
    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 */
    int opnd;			/* Integer representation of an operand */
    int litIndex;		/* Literal pool index of a constant */
    int 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.







|


|







1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
    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 */
    Tcl_Size operand1Len;	/* String length of the operand */
    int opnd;			/* Integer representation of an operand */
    int litIndex;		/* Literal pool index of a constant */
    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
	    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);
	    goto cleanup;
	}
	BBEmitInstInt1(assemEnvPtr, tblIdx, opnd, opnd);
	break;

    case ASSEM_CONCAT1:
	if (parsePtr->numWords != 2) {







|
|







1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
	    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", (void *)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
	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);
	    }
	    goto cleanup;
	}
	BBEmitInstInt4(assemEnvPtr, tblIdx, opnd, opnd);
	break;

    case ASSEM_LVT:







|







1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
	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", (void *)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
     *
     * 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;
    int savedExceptArrayNext = envPtr->exceptArrayNext;

    envPtr->currStackDepth = 0;
    envPtr->maxStackDepth = 0;

    StartBasicBlock(assemEnvPtr, BB_FALLTHRU, NULL);
    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:







|
|






|







1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
     *
     * 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.
     */

    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) {
    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:
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
 */

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_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;

    if (Tcl_ListObjGetElements(interp, jumps, &objc, &objv) != 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);
	}
	return TCL_ERROR;



    }

    /*
     * Allocate the jumptable.
     */

    jtPtr = (JumptableInfo*)Tcl_Alloc(sizeof(JumptableInfo));







|












|

|







|


>
>
>







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
 */

static int
CreateMirrorJumpTable(
    AssemblyEnv* assemEnvPtr,	/* Assembly environment */
    Tcl_Obj* jumps)		/* List of alternating keywords and labels */
{
    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. */
    Tcl_Size i;

    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", (void *)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
	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");
		DeleteMirrorJumpTable(jtPtr);
		return TCL_ERROR;
	    }
	}
	Tcl_SetHashValue(hashEntry, objv[i+1]);
	Tcl_IncrRefCount(objv[i+1]);
    }







|







2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
	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", (void *)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

    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);
	}
	return TCL_ERROR;
    }
    *tokenPtrPtr = TokenAfter(*tokenPtrPtr);
    Tcl_IncrRefCount(operandObj);
    *operandObjPtr = operandObj;
    return TCL_OK;







|







2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117

    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", (void *)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
 *-----------------------------------------------------------------------------
 */

static int
GetListIndexOperand(
    AssemblyEnv* assemEnvPtr,	/* Assembly environment */
    Tcl_Token** tokenPtrPtr,	/* Current token from the parser */
    int* result)		/* OUTPUT: Integer extracted 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







|







2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
 *-----------------------------------------------------------------------------
 */

static int
GetListIndexOperand(
    AssemblyEnv* assemEnvPtr,	/* Assembly environment */
    Tcl_Token** tokenPtrPtr,	/* Current token from the parser */
    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
 * 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
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 */

    if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &varNameObj) != TCL_OK) {
	return -1;
    }
    varNameStr = TclGetStringFromObj(varNameObj, &varNameLen);
    if (CheckNamespaceQualifiers(interp, varNameStr, varNameLen)) {
	Tcl_DecrRefCount(varNameObj);
	return -1;
    }
    localVar = TclFindCompiledLocal(varNameStr, varNameLen, 1, envPtr);
    Tcl_DecrRefCount(varNameObj);
    if (localVar == -1) {
	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);
	}
	return -1;
    }
    *tokenPtrPtr = TokenAfter(tokenPtr);
    return localVar;
}

/*
 *-----------------------------------------------------------------------------







|













|
|


|




|



|




|

|







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
 * 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 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;
    Tcl_Size varNameLen;
    Tcl_Size localVar;		/* Index of the variable in the LVT */

    if (GetNextOperand(assemEnvPtr, tokenPtrPtr, &varNameObj) != TCL_OK) {
	return TCL_INDEX_NONE;
    }
    varNameStr = TclGetStringFromObj(varNameObj, &varNameLen);
    if (CheckNamespaceQualifiers(interp, varNameStr, varNameLen)) {
	Tcl_DecrRefCount(varNameObj);
	return TCL_INDEX_NONE;
    }
    localVar = TclFindCompiledLocal(varNameStr, varNameLen, 1, envPtr);
    Tcl_DecrRefCount(varNameObj);
    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", (void *)NULL);
	}
	return TCL_INDEX_NONE;
    }
    *tokenPtrPtr = TokenAfter(tokenPtr);
    return localVar;
}

/*
 *-----------------------------------------------------------------------------
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
{
    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);
	    return TCL_ERROR;
	}
    }
    return TCL_OK;
}

/*







|







2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
{
    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, (void *)NULL);
	    return TCL_ERROR;
	}
    }
    return TCL_OK;
}

/*
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
    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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------







|







2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
    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", (void *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
    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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------







|







2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
    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", (void *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
    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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------







|







2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
    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", (void *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
    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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------







|







2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
    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", (void *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-----------------------------------------------------------------------------
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
	 * 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);
	}
	return TCL_ERROR;
    }

    /*
     * This is the first appearance of the label in the code.
     */







|







2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
	 * 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,
		    (void *)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
    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);
	Tcl_SetErrorLine(interp, bbPtr->jumpLine);
    }
}

/*
 *-----------------------------------------------------------------------------
 *







|







2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
    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), (void *)NULL);
	Tcl_SetErrorLine(interp, bbPtr->jumpLine);
    }
}

/*
 *-----------------------------------------------------------------------------
 *
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247

	    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);
		AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr);
	    }
	    return TCL_ERROR;
	}
	offset += tclInstructionTable[opcode].numBytes;
    }
    return TCL_OK;







|







3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250

	    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", (void *)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

static int
CheckStack(
    AssemblyEnv* assemEnvPtr)	/* Assembly environment */
{
    CompileEnv* envPtr = assemEnvPtr->envPtr;
				/* Compilation environment */
    int 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,







|







3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330

static int
CheckStack(
    AssemblyEnv* assemEnvPtr)	/* Assembly environment */
{
    CompileEnv* envPtr = assemEnvPtr->envPtr;
				/* Compilation environment */
    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
		    "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);
	}
	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







|







3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
		    "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", (void *)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
     * 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);
	    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);
	    AddBasicBlockRangeToErrorInfo(assemEnvPtr, blockPtr);
	    Tcl_SetErrorLine(interp, blockPtr->startLine);
	}
	return TCL_ERROR;
    }

    /*







|


















|







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
     * 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", (void *)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", (void *)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
	 */

	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);
	    }
	    return TCL_ERROR;
	}

	/*
	 * Record stack usage.
	 */







|







3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
	 */

	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", (void *)NULL);
	    }
	    return TCL_ERROR;
	}

	/*
	 * Record stack usage.
	 */
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
	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);
	}
	return TCL_ERROR;
    }
    if (state > bbPtr->catchState) {
	bbPtr->catchState = state;
	changed = 1;
    }







|







3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
	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", (void *)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
	 */

	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);
	    }
	    return TCL_ERROR;
	}
	fallThruEnclosing = enclosing->enclosingCatch;
	fallThruState = enclosing->catchState;
	--catchDepth;
    }







|







3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
	 */

	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", (void *)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

    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);
	}
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*







|







3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880

    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", (void *)NULL);
	}
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
	     */

	    block = catches[catchDepth];
	    catchIndices[catchDepth] =
		    TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
	    range = envPtr->exceptArrayPtr + catchIndices[catchDepth];
	    range->nestingLevel = envPtr->exceptDepth + catchDepth;
	    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:"







|







4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
	     */

	    block = catches[catchDepth];
	    catchIndices[catchDepth] =
		    TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
	    range = envPtr->exceptArrayPtr + catchIndices[catchDepth];
	    range->nestingLevel = envPtr->exceptDepth + catchDepth;
	    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
    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
				 * 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;








|







4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
    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 */
    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
	    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) {
		    envPtr->maxExceptDepth = range->nestingLevel + 1;
		}
	    }

	    /*
	     * Walk through the bytecode of the basic block, and relocate
	     * INST_BEGIN_CATCH4 instructions to the new locations







|







4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
	    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 + 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

/*
 *-----------------------------------------------------------------------------
 *
 * DupAssembleCodeInternalRep --
 *
 *	Part of the Tcl object type implementation for Tcl assembly language
 *	bytecode. We do not copy the bytecode intrep. 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,
 *	as we do for lists and dicts.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.







|








|







4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309

/*
 *-----------------------------------------------------------------------------
 *
 * DupAssembleCodeInternalRep --
 *
 *	Part of the Tcl object type implementation for Tcl assembly language
 *	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 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

static void
FreeAssembleCodeInternalRep(
    Tcl_Obj *objPtr)
{
    ByteCode *codePtr;

    ByteCodeGetIntRep(objPtr, &assembleCodeType, codePtr);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|












4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358

static void
FreeAssembleCodeInternalRep(
    Tcl_Obj *objPtr)
{
    ByteCode *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
/*
 * 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.
 *
 * 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. */
    Tcl_AsyncProc *proc;	/* Procedure to call when handler is
				 * invoked. */
    ClientData 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. */

} 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;








/*
 *----------------------------------------------------------------------
 *
 * TclFinalizeAsync --
 *
 *	Finalizes the mutex in the thread local data structure for the async
 *	subsystem.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Forgets knowledge of the mutex should it have been created.
 *
 *----------------------------------------------------------------------
 */

void
TclFinalizeAsync(void)
{


    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

















    if (tsdPtr->asyncMutex != NULL) {








	Tcl_MutexFinalize(&tsdPtr->asyncMutex);




    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncCreate --







|
|


















|
|
|


|







>



<
<
<
<
<
<
<










<
<


>
>
>
>
>
>
>






|






|







>
>
|
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44







45
46
47
48
49
50
51
52
53
54


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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 © 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, *prevPtr;
				/* Next, previous in list of all handlers
				 * for the process. */
    Tcl_AsyncProc *proc;	/* Procedure to call when handler is
				 * invoked. */
    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 {







    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. */


} 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 thread local data structure for the async
 *	subsystem.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Cleans up left-over async handlers for the calling thread.
 *
 *----------------------------------------------------------------------
 */

void
TclFinalizeAsync(void)
{
    AsyncHandler *token, *toDelete = NULL;
    Tcl_ThreadId self = Tcl_GetCurrentThread();

    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 (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
 *----------------------------------------------------------------------
 */

Tcl_AsyncHandler
Tcl_AsyncCreate(
    Tcl_AsyncProc *proc,	/* Procedure to call when handler is
				 * invoked. */
    ClientData 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->proc = proc;
    asyncPtr->clientData = clientData;
    asyncPtr->originTsd = tsdPtr;
    asyncPtr->originThrdId = Tcl_GetCurrentThread();


    Tcl_MutexLock(&tsdPtr->asyncMutex);
    if (tsdPtr->firstHandler == NULL) {
	tsdPtr->firstHandler = asyncPtr;
    } else {

	tsdPtr->lastHandler->nextPtr = asyncPtr;
    }
    tsdPtr->lastHandler = asyncPtr;
    Tcl_MutexUnlock(&tsdPtr->asyncMutex);
    return (Tcl_AsyncHandler) asyncPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncMark --







|







>




>

|
|
|

>
|

|
|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
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. */
    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(&asyncMutex);
    if (firstHandler == NULL) {
	firstHandler = asyncPtr;
    } else {
	asyncPtr->prevPtr = lastHandler;
	lastHandler->nextPtr = asyncPtr;
    }
    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

void
Tcl_AsyncMark(
    Tcl_AsyncHandler async)		/* Token for handler. */
{
    AsyncHandler *token = (AsyncHandler *) async;

    Tcl_MutexLock(&token->originTsd->asyncMutex);
    token->ready = 1;
    if (!token->originTsd->asyncActive) {
	token->originTsd->asyncReady = 1;
	Tcl_ThreadAlert(token->originThrdId);
    }
    Tcl_MutexUnlock(&token->originTsd->asyncMutex);









































































}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncInvoke --
 *







|





|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
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(&asyncMutex);
    token->ready = 1;
    if (!token->originTsd->asyncActive) {
	token->originTsd->asyncReady = 1;
	Tcl_ThreadAlert(token->originThrdId);
    }
    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
				 * 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_MutexLock(&tsdPtr->asyncMutex);

    if (tsdPtr->asyncReady == 0) {
	Tcl_MutexUnlock(&tsdPtr->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;
		asyncPtr = asyncPtr->nextPtr) {



	    if (asyncPtr->ready) {
		break;
	    }
	}
	if (asyncPtr == NULL) {
	    break;
	}
	asyncPtr->ready = 0;
	Tcl_MutexUnlock(&tsdPtr->asyncMutex);
	code = asyncPtr->proc(asyncPtr->clientData, interp, code);
	Tcl_MutexLock(&tsdPtr->asyncMutex);
    }
    tsdPtr->asyncActive = 0;
    Tcl_MutexUnlock(&tsdPtr->asyncMutex);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncDelete --







>

|


|



















|

>
>
>








|

|


|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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(&asyncMutex);

    if (tsdPtr->asyncReady == 0) {
	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 = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->originThrdId != self) {
		continue;
	    }
	    if (asyncPtr->ready) {
		break;
	    }
	}
	if (asyncPtr == NULL) {
	    break;
	}
	asyncPtr->ready = 0;
	Tcl_MutexUnlock(&asyncMutex);
	code = asyncPtr->proc(asyncPtr->clientData, interp, code);
	Tcl_MutexLock(&asyncMutex);
    }
    tsdPtr->asyncActive = 0;
    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
 *----------------------------------------------------------------------
 */

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);
    if (tsdPtr->firstHandler != NULL) {
	prevPtr = thisPtr = tsdPtr->firstHandler;
	while (thisPtr != NULL && thisPtr != asyncPtr) {
	    prevPtr = thisPtr;
	    thisPtr = thisPtr->nextPtr;
	}
	if (thisPtr == NULL) {
	    Tcl_Panic("Tcl_AsyncDelete: cannot find async handler");
	}
	if (asyncPtr == tsdPtr->firstHandler) {
	    tsdPtr->firstHandler = asyncPtr->nextPtr;
	} else {
	    prevPtr->nextPtr = asyncPtr->nextPtr;
	}
	if (asyncPtr == tsdPtr->lastHandler) {
	    tsdPtr->lastHandler = prevPtr;
	}
    }



    Tcl_MutexUnlock(&tsdPtr->asyncMutex);
    Tcl_Free(asyncPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AsyncReady --







<

<









<
<
<
<
<
<
<
|
<
<
<
|
|
<
|
|

<
<
|
|
<
|
|


>
>
>
|







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. */
{

    AsyncHandler *asyncPtr = (AsyncHandler *) async;


    /*
     * Assure early handling of the constraint
     */

    if (asyncPtr->originThrdId != Tcl_GetCurrentThread()) {
	Tcl_Panic("Tcl_AsyncDelete: async handler deleted by the wrong thread");
    }








    Tcl_MutexLock(&asyncMutex);



    if (asyncPtr->prevPtr == NULL) {
	firstHandler = asyncPtr->nextPtr;

	if (firstHandler == NULL) {
	    lastHandler = NULL;
	}


    } else {
	asyncPtr->prevPtr->nextPtr = asyncPtr->nextPtr;

	if (asyncPtr == lastHandler) {
	    lastHandler = asyncPtr->prevPtr;
	}
    }
    if (asyncPtr->nextPtr != NULL) {
	asyncPtr->nextPtr->prevPtr = asyncPtr->prevPtr;
    }
    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
/*
 * 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 <[email protected]>
 * Copyright (c) 2006-2008 by Joe Mistachkin.  All rights reserved.
 * Copyright (c) 2008 Miguel Sofer <[email protected]>
 *
 * 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"







|
|
|
|
|
|
|







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 © 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 <[email protected]>
 * Copyright © 2006-2008 Joe Mistachkin.  All rights reserved.
 * Copyright © 2008 Miguel Sofer <[email protected]>
 *
 * 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"
60
61
62
63
64
65
66



































67
68
69
70
71
72
73
 */
#define TCL_FPCLASSIFY_MODE 2
#endif /* !fpclassify */
/* actually there is no fallback to builtin fpclassify */
#endif /* !TCL_FPCLASSIFY_MODE */





































#define INTERP_STACK_INITIAL_SIZE 2000
#define CORO_STACK_INITIAL_SIZE    200

/*
 * Determine whether we're using IEEE floating point
 */








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
 */
#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

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. */
    int flags;			/* Additional flags */
} CancelInfo;
static Tcl_HashTable cancelTable;
static int cancelTableInitialized = 0;	/* 0 means not yet initialized. */
TCL_DECLARE_MUTEX(cancelLock);

/*







|
|







124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139

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. */
    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);

/*
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

152
153
154
155
156
157
158
 * Static functions in this file:
 */

static Tcl_ObjCmdProc   BadEnsembleSubcommand;
static char *		CallCommandTraces(Interp *iPtr, Command *cmdPtr,
			    const char *oldName, const char *newName,
			    int flags);
static int		CancelEvalProc(ClientData 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);
#ifdef USE_DTRACE
static Tcl_ObjCmdProc	DTraceObjCmd;
static Tcl_NRPostProc	DTraceCmdReturn;
#else
#   define DTraceCmdReturn	NULL
#endif /* USE_DTRACE */

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;







|


|
|
|






>







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
 * Static functions in this file:
 */

static Tcl_ObjCmdProc   BadEnsembleSubcommand;
static char *		CallCommandTraces(Interp *iPtr, Command *cmdPtr,
			    const char *oldName, const char *newName,
			    int flags);
static int		CancelEvalProc(void *clientData,
			    Tcl_Interp *interp, int code);
static int		CheckDoubleResult(Tcl_Interp *interp, double dResult);
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;
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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 COROUTINE_ARGUMENTS_SINGLE_OPTIONAL     (-1)
#define COROUTINE_ARGUMENTS_ARBITRARY           (-2)

/*
 * The following structure define the commands in the Tcl core.
 */







|
|







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
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    NULL
#define CORO_ACTIVATE_YIELDM   INT2PTR(1)

#define COROUTINE_ARGUMENTS_SINGLE_OPTIONAL     (-1)
#define COROUTINE_ARGUMENTS_ARBITRARY           (-2)

/*
 * The following structure define the commands in the Tcl core.
 */
259
260
261
262
263
264
265










266
267
268
269
270
271
272
273
274
275
276

277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
                                 * hack because it is expected by security
                                 * policies in the wild. */
} UnsafeEnsembleInfo;

/*
 * The built-in commands, and the functions that implement them:
 */











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},

    {"continue",	Tcl_ContinueObjCmd,	TclCompileContinueCmd,	NULL,	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},
    {"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},

    {"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},
    {"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},

    {"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},
    {"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},







>
>
>
>
>
>
>
>
>
>











>

















>












>



|







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
                                 * 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},
    {"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},
    {"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},
    {"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",		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},
584
585
586
587
588
589
590
















































































































591
592
593
594
595
596
597
    }
    Tcl_MutexUnlock(&commandTypeLock);
}

/*
 *----------------------------------------------------------------------
 *
















































































































 * Tcl_CreateInterp --
 *
 *	Create a new TCL command interpreter.
 *
 * Results:
 *	The return value is a token for the interpreter, which may be used in
 *	calls to functions like Tcl_CreateCmd, Tcl_Eval, or Tcl_DeleteInterp.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    }
    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. */
{
    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?option?");
	return TCL_ERROR;
    }
    if (objc == 2) {
	Tcl_Size len;
	const char *arg = TclGetStringFromObj(objv[1], &len);
	if (len == 7 && !strcmp(arg, "version")) {
	    char buf[80];
	    const char *p = strchr((char *)clientData, '.');
	    if (p) {
		const char *q = strchr(p+1, '.');
		const char *r = strchr(p+1, '+');
		p = (q < r) ? q : r;
	    }
	    if (p) {
		memcpy(buf, (char *)clientData, p - (char *)clientData);
		buf[p - (char *)clientData] = '\0';
		Tcl_AppendResult(interp, buf, (char *)NULL);
	    }
	    return TCL_OK;
	} else if (len == 10 && !strcmp(arg, "patchlevel")) {
	    char buf[80];
	    const char *p = strchr((char *)clientData, '+');
	    if (p) {
		memcpy(buf, (char *)clientData, p - (char *)clientData);
		buf[p - (char *)clientData] = '\0';
		Tcl_AppendResult(interp, buf, (char *)NULL);
	    }
	    return TCL_OK;
	} else if (len == 6 && !strcmp(arg, "commit")) {
	    const char *q, *p = strchr((char *)clientData, '+');
	    if (p) {
		if ((q = strchr(p, '.'))) {
		    char buf[80];
		    memcpy(buf, p+1, q - p - 1);
		    buf[q - p - 1] = '\0';
		    Tcl_AppendResult(interp, buf, (char *)NULL);
		} else {
		    Tcl_AppendResult(interp, p+1, (char *)NULL);
		}
	    }
	    return TCL_OK;
	} else if (len == 8 && !strcmp(arg, "compiler")) {
	    const char *p = strchr((char *)clientData, '.');
	    while (p) {
		if (!strncmp(p+1, "clang-", 6) || !strncmp(p+1, "gcc-", 4)
			    || !strncmp(p+1, "icc-", 4) || !strncmp(p+1, "msvc-", 5)) {
		    const char *q = strchr(p+1, '.');
		    if (q) {
			char buf[16];
			memcpy(buf, p+1, q - p - 1);
			buf[q - p - 1] = '\0';
			Tcl_AppendResult(interp, buf, (char *)NULL);
		    } else {
			Tcl_AppendResult(interp, p+1, (char *)NULL);
		    }
		    return TCL_OK;
		}
		p = strchr(p+1, '.');
	    }
	    Tcl_AppendResult(interp, "0", (char *)NULL);
	    return TCL_OK;
	}
	const char *p = strchr((char *)clientData, '.');
	while (p) {
	    if (!strncmp(p+1, arg, len) && ((p[len+1] == '.') || (p[len+1] == '\0'))) {
		Tcl_AppendResult(interp, "1", (char *)NULL);
		return TCL_OK;
	    }
	    p = strchr(p+1, '.');
	}
	Tcl_AppendResult(interp, "0", (char *)NULL);
	return TCL_OK;
    }
    Tcl_AppendResult(interp, (char *)clientData, (char *)NULL);
    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.
 *
 * Results:
 *	The return value is a token for the interpreter, which may be used in
 *	calls to functions like Tcl_CreateCmd, Tcl_Eval, or Tcl_DeleteInterp.
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
	short s;
    } order;
#ifdef TCL_COMPILE_STATS
    ByteCodeStats *statsPtr;
#endif /* TCL_COMPILE_STATS */
    char mathFuncName[32];
    CallFrame *framePtr;

    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)) {







<
|







782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
	short s;
    } order;
#ifdef TCL_COMPILE_STATS
    ByteCodeStats *statsPtr;
#endif /* TCL_COMPILE_STATS */
    char mathFuncName[32];
    CallFrame *framePtr;

    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
	    Tcl_InitHashTable(&cancelTable, TCL_ONE_WORD_KEYS);
	    cancelTableInitialized = 1;
	}

	Tcl_MutexUnlock(&cancelLock);
    }


    if (commandTypeInit == 0) {
        TclRegisterCommandTypeName(TclObjInterpProc, "proc");
        TclRegisterCommandTypeName(TclEnsembleImplementationCmd, "ensemble");
        TclRegisterCommandTypeName(TclAliasObjCmd, "alias");
        TclRegisterCommandTypeName(TclLocalAliasObjCmd, "alias");
        TclRegisterCommandTypeName(TclChildObjCmd, "interp");
        TclRegisterCommandTypeName(TclInvokeImportedCmd, "import");







>







813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
	    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");
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695

    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();
    Tcl_IncrRefCount(iPtr->objResultPtr);
    iPtr->handle = TclHandleCreate(iPtr);
    iPtr->globalNsPtr = NULL;
    iPtr->hiddenCmdTablePtr = NULL;
    iPtr->interpInfo = NULL;

    iPtr->optimizer = TclOptimizeBytecode;







|







842
843
844
845
846
847
848
849
850
851
852
853
854
855
856

    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;
    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
    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;





    /* TIP #268 */
#if (TCL_RELEASE_LEVEL == TCL_FINAL_RELEASE)
    if (getenv("TCL_PKG_PREFER_LATEST") == NULL) {
	iPtr->packagePrefer = PKG_PREFER_STABLE;
    } else
#endif







>
>
>
>







900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
    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
    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();
				/* Another empty object. */
    Tcl_IncrRefCount(iPtr->emptyObjPtr);
    iPtr->threadId = Tcl_GetCurrentThread();

    /* TIP #378 */
#ifdef TCL_INTERP_DEBUG_FRAME
    iPtr->flags |= INTERP_DEBUG_FRAME;







|







927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
    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. */
    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;
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840

    iPtr->chanMsg = NULL;

    /*
     * TIP #285, Script cancellation support.
     */

    iPtr->asyncCancelMsg = Tcl_NewObj();

    cancelInfo = (CancelInfo *)Tcl_Alloc(sizeof(CancelInfo));
    cancelInfo->interp = interp;

    iPtr->asyncCancel = Tcl_AsyncCreate(CancelEvalProc, cancelInfo);
    cancelInfo->async = iPtr->asyncCancel;
    cancelInfo->result = NULL;







|







991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005

    iPtr->chanMsg = NULL;

    /*
     * TIP #285, Script cancellation support.
     */

    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
    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
     * 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->clientData = cmdPtr;
	    cmdPtr->objProc = cmdInfoPtr->objProc;
	    cmdPtr->objClientData = NULL;
	    cmdPtr->deleteProc = NULL;
	    cmdPtr->deleteData = NULL;
	    cmdPtr->flags = 0;
            if (cmdInfoPtr->flags & CMD_COMPILES_EXPANDED) {







|
|
|
<
<
<
<
<


















|







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
    iPtr->allocCache = NULL;
#endif
    iPtr->pendingObjDataPtr = NULL;
    iPtr->asyncReadyPtr = TclGetAsyncReadyPtr();
    iPtr->deferredCallbacks = NULL;

    /*
     * 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.





     */

    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 = 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) {
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
     * 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

     */

    Tcl_PkgProvideEx(interp, "Tcl", TCL_PATCH_LEVEL, &tclStubs);









    if (TclTommath_Init(interp) != TCL_OK) {
	Tcl_Panic("%s", Tcl_GetStringResult(interp));
    }

    if (TclOOInit(interp) != TCL_OK) {
	Tcl_Panic("%s", Tcl_GetStringResult(interp));







<
<
<
<
<
<
<
<
<
<
<



>



>
>
>
>
>
>
>
>







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
     * 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);












    /*
     * 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));
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171

    TOP_CB(iPtr) = NULL;
    return interp;
}

static void
DeleteOpCmdClientData(
    ClientData clientData)
{
    TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;

    Tcl_Free(occdPtr);
}

/*







|







1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329

    TOP_CB(iPtr) = NULL;
    return interp;
}

static void
DeleteOpCmdClientData(
    void *clientData)
{
    TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;

    Tcl_Free(occdPtr);
}

/*
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
        Tcl_InitHashTable(&commandTypeTable, TCL_ONE_WORD_KEYS);
        commandTypeInit = 1;
    }
    if (nameStr != NULL) {
        int isNew;

        hPtr = Tcl_CreateHashEntry(&commandTypeTable,
                (void *) implementationProc, &isNew);
        Tcl_SetHashValue(hPtr, (void *) nameStr);
    } else {
        hPtr = Tcl_FindHashEntry(&commandTypeTable,
                (void *) implementationProc);
        if (hPtr != NULL) {
            Tcl_DeleteHashEntry(hPtr);
        }
    }
    Tcl_MutexUnlock(&commandTypeLock);
}








|



|







1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
        Tcl_InitHashTable(&commandTypeTable, TCL_ONE_WORD_KEYS);
        commandTypeInit = 1;
    }
    if (nameStr != NULL) {
        int isNew;

        hPtr = Tcl_CreateHashEntry(&commandTypeTable,
                implementationProc, &isNew);
        Tcl_SetHashValue(hPtr, (void *) nameStr);
    } else {
        hPtr = Tcl_FindHashEntry(&commandTypeTable,
                implementationProc);
        if (hPtr != NULL) {
            Tcl_DeleteHashEntry(hPtr);
        }
    }
    Tcl_MutexUnlock(&commandTypeLock);
}

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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
BadEnsembleSubcommand(
    ClientData 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);
    return TCL_ERROR;
}

/*
 *--------------------------------------------------------------
 *
 * Tcl_CallWhenDeleted --







|









|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
BadEnsembleSubcommand(
    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", (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
 */

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. */
{
    Interp *iPtr = (Interp *) interp;
    static Tcl_ThreadDataKey assocDataCounterKey;
    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);
    (*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);







|










|







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
 */

void
Tcl_CallWhenDeleted(
    Tcl_Interp *interp,		/* Interpreter to watch. */
    Tcl_InterpDeleteProc *proc,	/* Function to call when interpreter is about
				 * to be deleted. */
    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 isNew;
    char buffer[32 + TCL_INTEGER_SPACE];
    AssocData *dPtr = (AssocData *)Tcl_Alloc(sizeof(AssocData));
    Tcl_HashEntry *hPtr;

    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
 */

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. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_HashTable *hTablePtr;
    Tcl_HashSearch hSearch;
    Tcl_HashEntry *hPtr;
    AssocData *dPtr;








|







1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
 */

void
Tcl_DontCallWhenDeleted(
    Tcl_Interp *interp,		/* Interpreter to watch. */
    Tcl_InterpDeleteProc *proc,	/* Function to call when interpreter is about
				 * to be deleted. */
    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

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. */
{
    Interp *iPtr = (Interp *) interp;
    AssocData *dPtr;
    Tcl_HashEntry *hPtr;
    int isNew;

    if (iPtr->assocData == NULL) {







|







1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630

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. */
    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
	return;
    }
    hPtr = Tcl_FindHashEntry(iPtr->assocData, name);
    if (hPtr == NULL) {
	return;
    }
    dPtr = (AssocData *)Tcl_GetHashValue(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
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. */
{







>




<




















|







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
	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_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.
 *
 *----------------------------------------------------------------------
 */

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
    iPtr->flags |= DELETED;
    iPtr->compileEpoch++;

    /*
     * Ensure that the interpreter is eventually deleted.
     */

    Tcl_EventuallyFree(interp, (Tcl_FreeProc *) DeleteInterpProc);
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteInterpProc --
 *







|







1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
    iPtr->flags |= DELETED;
    iPtr->compileEpoch++;

    /*
     * Ensure that the interpreter is eventually deleted.
     */

    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
 *	by the interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteInterpProc(
    Tcl_Interp *interp)		/* Interpreter to delete. */
{

    Interp *iPtr = (Interp *) interp;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_HashTable *hTablePtr;
    ResolverScheme *resPtr, *nextResPtr;
    int i;

    /*
     * Punt if there is an error in the Tcl_Release/Tcl_Preserve matchup,
	 * unless we are exiting.
     */

    if ((iPtr->numLevels > 0) && !TclInExit()) {







|

>





|







1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
 *	by the interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteInterpProc(
    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;
    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

    /*
     * 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);
    if (hPtr != NULL) {
	CancelInfo *cancelInfo = (CancelInfo *)Tcl_GetHashValue(hPtr);

	if (cancelInfo != NULL) {
	    if (cancelInfo->result != NULL) {
		Tcl_Free(cancelInfo->result);
	    }







|







1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881

    /*
     * TIP #285, Script cancellation support. Delete this interp from the
     * global hash table of CancelInfo structs.
     */

    Tcl_MutexLock(&cancelLock);
    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
	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) {
	AssocData *dPtr;

	hTablePtr = iPtr->assocData;
	iPtr->assocData = NULL;




	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);

    }

    /*
     * Pop the root frame pointer and finish deleting the global
     * namespace. The order is important [Bug 1658572].
     */








<
<
<
<

|



<
>
>
>
>




<



>




>







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
	for (; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    Tcl_DeleteCommandFromToken(interp, (Tcl_Command)Tcl_GetHashValue(hPtr));
	}
	Tcl_DeleteHashTable(hTablePtr);
	Tcl_Free(hTablePtr);
    }






    if (iPtr->assocData != NULL) {
	AssocData *dPtr;

	hTablePtr = iPtr->assocData;

	/*
	 * 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);

	    if (dPtr->proc != NULL) {
		dPtr->proc(dPtr->clientData, interp);
	    }
	    Tcl_DeleteHashEntry(hPtr);
	    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
	    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++) {
	    Tcl_Free(eclPtr->loc[i].line);
	}

	if (eclPtr->loc != NULL) {
	    Tcl_Free(eclPtr->loc);
	}








|







2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
	    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++) {
	    Tcl_Free(eclPtr->loc[i].line);
	}

	if (eclPtr->loc != NULL) {
	    Tcl_Free(eclPtr->loc);
	}

2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
     * 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);
	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.







|







2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
     * 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", (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.
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
     * 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);
	return TCL_ERROR;
    }

    /*
     * Initialize the hidden command table if necessary.
     */








|







2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
     * 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", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Initialize the hidden command table if necessary.
     */

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
     */

    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);
	return TCL_ERROR;
    }

    /*
     * NB: This code is currently 'like' a rename to a specialy set apart 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.
     */

    if (cmdPtr->hPtr != NULL) {
	Tcl_DeleteHashEntry(cmdPtr->hPtr);
	cmdPtr->hPtr = NULL;
	cmdPtr->cmdEpoch++;
    }







|




|






|
|







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
     */

    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", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * 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
     * to invalidate any cached references that point to the command.
     */

    if (cmdPtr->hPtr != NULL) {
	Tcl_DeleteHashEntry(cmdPtr->hPtr);
	cmdPtr->hPtr = NULL;
	cmdPtr->cmdEpoch++;
    }
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
     * 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);
	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);
	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
	 * than 'nicely' erroring out ?
	 */

	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"trying to expose a non-global command namespace command",
		-1));
	return TCL_ERROR;







|
















|












|







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
     * 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", (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, (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 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));
	return TCL_ERROR;
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
     * 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);
	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,







|







2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
     * 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", (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
 *	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
 *	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. */
    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;







|















|







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
 *	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
 *	(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. */
    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;
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
    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->objClientData = cmdPtr;
    cmdPtr->proc = proc;
    cmdPtr->clientData = clientData;
    cmdPtr->deleteProc = deleteProc;
    cmdPtr->deleteData = clientData;
    cmdPtr->flags = 0;
    cmdPtr->importRefPtr = NULL;







|







2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
    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 = 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
 *	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.
 *
 *----------------------------------------------------------------------
 */


































































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
				 * function. */
    Tcl_CmdDeleteProc *deleteProc
				/* If not NULL, gives a function to call when
				 * this command is deleted. */
)
{
    Interp *iPtr = (Interp *) interp;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|







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
 *	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. */
    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. */
)
{
    Interp *iPtr = (Interp *) interp;
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
TclCreateObjCommandInNs(
    Tcl_Interp *interp,
    const char *cmdName,	/* Name of command, without any namespace
                                 * 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
				 * function. */
    Tcl_CmdDeleteProc *deleteProc)
				/* If not NULL, gives a function to call when
				 * this command is deleted. */
{
    int deleted = 0, isNew = 0;
    Command *cmdPtr;







|







2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
TclCreateObjCommandInNs(
    Tcl_Interp *interp,
    const char *cmdName,	/* Name of command, without any namespace
                                 * components. */
    Tcl_Namespace *namesp,   /* The namespace to create the command in */
    Tcl_ObjCmdProc *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. */
{
    int deleted = 0, isNew = 0;
    Command *cmdPtr;
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
    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->clientData = cmdPtr;
    cmdPtr->deleteProc = deleteProc;
    cmdPtr->deleteData = clientData;
    cmdPtr->flags = 0;
    cmdPtr->importRefPtr = NULL;
    cmdPtr->tracePtr = NULL;
    cmdPtr->nreProc = NULL;







|







2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
    cmdPtr->hPtr = hPtr;
    cmdPtr->nsPtr = nsPtr;
    cmdPtr->refCount = 1;
    cmdPtr->cmdEpoch = 0;
    cmdPtr->compileProc = NULL;
    cmdPtr->objProc = proc;
    cmdPtr->objClientData = clientData;
    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
    TclResetShadowedCmdRefs(interp, cmdPtr);
    return (Tcl_Command) cmdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInvokeStringCommand --
 *
 *	"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.
 *
 *----------------------------------------------------------------------
 */

int
TclInvokeStringCommand(
    ClientData 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 **)







|












|





|
|







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
    TclResetShadowedCmdRefs(interp, cmdPtr);
    return (Tcl_Command) cmdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * 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,
 *	InvokeStringCommand allocates and frees storage.
 *
 *----------------------------------------------------------------------
 */

int
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
     */

    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







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2998
2999
3000
3001
3002
3003
3004

































































3005
3006
3007
3008
3009
3010
3011
     */

    result = cmdPtr->proc(cmdPtr->clientData, interp, objc, argv);

    TclStackFree(interp, (void *) argv);
    return result;
}


































































/*
 *----------------------------------------------------------------------
 *
 * TclRenameCommand --
 *
 *	Called to give an existing Tcl command a different name. Both the old
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
    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",
		oldName));
        Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", oldName, 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();
    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.
     */

    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);
	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);
	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).







|














|






|








|







|







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
    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",
		oldName));
        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;
    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_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", (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", (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).
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
 *	returned. If the command doesn't exist then 0 is returned.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */





































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->objClientData = cmdPtr;
	cmdPtr->nreProc = NULL;
    } else {
	if (infoPtr->objProc != cmdPtr->objProc) {
	    cmdPtr->nreProc = NULL;
	    cmdPtr->objProc = infoPtr->objProc;
	}
	cmdPtr->objClientData = infoPtr->objClientData;
    }


























    cmdPtr->deleteProc = infoPtr->deleteProc;
    cmdPtr->deleteData = infoPtr->deleteData;


    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCommandInfo --







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>







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
 *	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 = 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;
	}
    }
    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

    if (cmd == NULL) {
	return 0;
    }

    /*
     * Set isNativeObjectProc 1 if objProc was registered by a call to
     * Tcl_CreateObjCommand. Otherwise set it to 0.

     */

    cmdPtr = (Command *) cmd;
    infoPtr->isNativeObjectProc =
	    (cmdPtr->objProc != TclInvokeStringCommand);
    infoPtr->objProc = cmdPtr->objProc;
    infoPtr->objClientData = cmdPtr->objClientData;
    infoPtr->proc = cmdPtr->proc;
    infoPtr->clientData = cmdPtr->clientData;










    infoPtr->deleteProc = cmdPtr->deleteProc;
    infoPtr->deleteData = cmdPtr->deleteData;

    infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;


    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCommandName --
 *
 *	Given a token returned by Tcl_CreateCommand, 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
				 * not have been deleted. */
{
    Command *cmdPtr = (Command *) command;

    if ((cmdPtr == NULL) || (cmdPtr->hPtr == NULL)) {
	/*
	 * This should only happen if command was "created" after the







|
>




|




>
>
>
>
>
>
>
>
>
>
|
|
>
|
|
>








|















|







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

    if (cmd == NULL) {
	return 0;
    }

    /*
     * Set isNativeObjectProc 1 if objProc was registered by a call to
     * 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 != 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->objProc2 = cmdWrapper2Proc;
	infoPtr->objClientData2 = cmdPtr;
    }
    infoPtr->namespacePtr = (Tcl_Namespace *) cmdPtr->nsPtr;
    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCommandName --
 *
 *	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_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
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCommandFullName --
 *
 *	Given a token returned by, e.g., Tcl_CreateCommand 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
				 * 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;







|


















|







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
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetCommandFullName --
 *
 *	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_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;
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432


3433
3434
3435
3436
3437
3438
3439
     * 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
     * traces.
     */

    cmdPtr->nsPtr->refCount++;

    if (cmdPtr->tracePtr != NULL) {
	CommandTrace *tracePtr;


	CallCommandTraces(iPtr,cmdPtr,NULL,NULL,TCL_TRACE_DELETE);

	/*
	 * Now delete these traces.
	 */

	tracePtr = cmdPtr->tracePtr;







|
<






>
>







3654
3655
3656
3657
3658
3659
3660
3661

3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
     * declares that a delete is in progress and that recursive deletes should
     * be ignored.
     */

    cmdPtr->flags |= CMD_DYING;

    /*
     * Call each functions and then delete the trace.

     */

    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
	    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) {







<







3832
3833
3834
3835
3836
3837
3838

3839
3840
3841
3842
3843
3844
3845
	    flags &= ~TCL_TRACE_RENAME;
	}
	if (flags == 0) {
	    return NULL;
	}
    }
    cmdPtr->flags |= CMD_TRACE_ACTIVE;


    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

    /*
     * 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.
 *
 *----------------------------------------------------------------------
 */

static int
CancelEvalProc(
    ClientData 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) {







<




















|






|







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

    /*
     * Restore the variable's flags, remove the record of our active traces,
     * and then return.
     */

    cmdPtr->flags &= ~CMD_TRACE_ACTIVE;

    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 cancellation message to the interpreter.
 *
 *----------------------------------------------------------------------
 */

static int
CancelEvalProc(
    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) {
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
     * 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));
	Tcl_SetErrorCode(interp, "TCL", "IDELETE",
		"attempt to call eval in deleted interpreter", NULL);
	return TCL_ERROR;
    }

    if (iPtr->execEnvPtr->rewind) {
	return TCL_ERROR;
    }








|







4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
     * 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));
	Tcl_SetErrorCode(interp, "TCL", "IDELETE",
		"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
    }

    /*
     * 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)) {
	return TCL_OK;
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "too many nested evaluations (infinite loop?)", -1));
    Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclResetCancellation --







|





|







4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
    }

    /*
     * 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)) {
	return TCL_OK;
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(
	    "too many nested evaluations (infinite loop?)", -1));
    Tcl_SetErrorCode(interp, "TCL", "LIMIT", "STACK", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclResetCancellation --
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
    /*
     * 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;

        /*
         * Setup errorCode variables so that we can differentiate between
         * being canceled and unwound.
         */

        if (iPtr->asyncCancelMsg != NULL) {







|







4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
    /*
     * 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;
        Tcl_Size length;

        /*
         * Setup errorCode variables so that we can differentiate between
         * being canceled and unwound.
         */

        if (iPtr->asyncCancelMsg != NULL) {
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
            id = "ICANCEL";
            if (length == 0) {
                message = "eval canceled";
            }
        }

        Tcl_SetObjResult(interp, Tcl_NewStringObj(message, -1));
        Tcl_SetErrorCode(interp, "TCL", "CANCEL", id, message, 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.
     */







|







4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
            id = "ICANCEL";
            if (length == 0) {
                message = "eval canceled";
            }
        }

        Tcl_SetObjResult(interp, Tcl_NewStringObj(message, -1));
        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

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. */
    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;







|







4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256

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. */
    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
    if (cancelTableInitialized != 1) {
	/*
	 * No CancelInfo hash table (Tcl_CreateInterp has never been called?)
	 */

	goto done;
    }
    hPtr = Tcl_FindHashEntry(&cancelTable, (char *) interp);
    if (hPtr == NULL) {
	/*
	 * No CancelInfo record for this interpreter.
	 */

	goto done;
    }







|







4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
    if (cancelTableInitialized != 1) {
	/*
	 * No CancelInfo hash table (Tcl_CreateInterp has never been called?)
	 */

	goto done;
    }
    hPtr = Tcl_FindHashEntry(&cancelTable, interp);
    if (hPtr == NULL) {
	/*
	 * No CancelInfo record for this interpreter.
	 */

	goto done;
    }
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
 *----------------------------------------------------------------------
 */

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_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_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







|


















|







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
 *----------------------------------------------------------------------
 */

int
Tcl_EvalObjv(
    Tcl_Interp *interp,		/* Interpreter in which to evaluate the
				 * command. Also used for error reporting. */
    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. */
    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
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
    TclNRAddCallback(interp, EvalObjvCore, cmdPtr, INT2PTR(flags),
	    INT2PTR(objc), objv);
    return TCL_OK;
}

static int
EvalObjvCore(
    ClientData 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_Obj **objv = (Tcl_Obj **)data[3];







|







4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
    TclNRAddCallback(interp, EvalObjvCore, cmdPtr, INT2PTR(flags),
	    INT2PTR(objc), objv);
    return TCL_OK;
}

static int
EvalObjvCore(
    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_Obj **objv = (Tcl_Obj **)data[3];
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
	    /*
	     * 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);
	    return TCL_ERROR;
	}
    }
    if (cmdPtr == NULL) {
	cmdPtr = TEOV_LookupCmdFromObj(interp, objv[0], lookupNsPtr);
	if (!cmdPtr) {
	    return TEOV_NotFound(interp, objc, objv, lookupNsPtr);







|







4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
	    /*
	     * 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", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    if (cmdPtr == NULL) {
	cmdPtr = TEOV_LookupCmdFromObj(interp, objv[0], lookupNsPtr);
	if (!cmdPtr) {
	    return TEOV_NotFound(interp, objc, objv, lookupNsPtr);
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
	    cmdPtr->nreProc ? cmdPtr->nreProc : cmdPtr->objProc,
	    cmdPtr->objClientData, INT2PTR(objc), objv);
    return TCL_OK;
}

static int
Dispatch(
    ClientData data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    Tcl_ObjCmdProc *objProc = (Tcl_ObjCmdProc *)data[0];
    ClientData clientData = data[1];
    int 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;

	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];

	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) {







|




|
|






|









|







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
	    cmdPtr->nreProc ? cmdPtr->nreProc : cmdPtr->objProc,
	    cmdPtr->objClientData, INT2PTR(objc), objv);
    return TCL_OK;
}

static int
Dispatch(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    Tcl_ObjCmdProc *objProc = (Tcl_ObjCmdProc *)data[0];
    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];
	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]; 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) {
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
	TCLNR_FREE(interp, callbackPtr);
    }
    return result;
}

static int
NRCommand(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;


    iPtr->numLevels--;

     /*
      * If there is a tailcall, schedule it next
      */

    if (data[1] && (data[1] != INT2PTR(1))) {



        TclNRAddCallback(interp, TclNRTailcallEval, data[1], NULL, NULL, NULL);
    }

    /* OPT ??
     * Do not interrupt a series of cleanups with async or limit checks:
     * just check at the end?
     */








|




>








>
>
>
|







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
	TCLNR_FREE(interp, callbackPtr);
    }
    return result;
}

static int
NRCommand(
    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 (data[1] && (data[1] != INT2PTR(1))) {
	listPtr = (Tcl_Obj *)data[1];
	data[1] = 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?
     */

4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473

    if (!(flags & TCL_EVAL_INVOKE)) {
	/*
	 * Error messages
	 */

	TclNRAddCallback(interp, TEOV_Error, INT2PTR(objc),
		(ClientData) objv, NULL, NULL);
    }

    if (iPtr->numLevels == 1) {
	/*
	 * No CONTINUE or BREAK at level 0, manage RETURN
	 */








|







4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712

    if (!(flags & TCL_EVAL_INVOKE)) {
	/*
	 * Error messages
	 */

	TclNRAddCallback(interp, TEOV_Error, INT2PTR(objc),
		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
    TclNRAddCallback(interp, TEOV_RestoreVarFrame, iPtr->varFramePtr, NULL,
	    NULL, NULL);
    iPtr->varFramePtr = iPtr->rootFramePtr;
}

static int
TEOV_RestoreVarFrame(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    ((Interp *) interp)->varFramePtr = (CallFrame *)data[0];
    return result;
}

static int
TEOV_Exception(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int allowExceptions = (PTR2INT(data[0]) & TCL_ALLOW_EXCEPTIONS);

    if (result != TCL_OK) {







|









|







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
    TclNRAddCallback(interp, TEOV_RestoreVarFrame, iPtr->varFramePtr, NULL,
	    NULL, NULL);
    iPtr->varFramePtr = iPtr->rootFramePtr;
}

static int
TEOV_RestoreVarFrame(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    ((Interp *) interp)->varFramePtr = (CallFrame *)data[0];
    return result;
}

static int
TEOV_Exception(
    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

    TclUnsetCancelFlags(iPtr);
    return result;
}

static int
TEOV_Error(
    ClientData 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_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







|






|







4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789

    TclUnsetCancelFlags(iPtr);
    return result;
}

static int
TEOV_Error(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *listPtr;
    const char *cmdString;
    Tcl_Size cmdLen;
    int 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
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
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[],
    Namespace *lookupNsPtr)
{
    Command * cmdPtr;
    Interp *iPtr = (Interp *) interp;
    int 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");
	}
    }

    /*
     * 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
     * itself.
     */

    Tcl_ListObjGetElements(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







|











|















|



|







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
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[],
    Namespace *lookupNsPtr)
{
    Command * cmdPtr;
    Interp *iPtr = (Interp *) interp;
    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("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 invocation
     * itself.
     */

    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
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
     */

    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);

	/*
	 * Release any resources we locked and allocated during the handler
	 * call.
	 */

	for (i = 0; i < handlerObjc; ++i) {







|







4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
     */

    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]), (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
    TclNRAddCallback(interp, TEOV_NotFoundCallback, INT2PTR(handlerObjc),
	    newObjv, savedNsPtr, NULL);
    return TclNREvalObjv(interp, newObjc, newObjv, TCL_EVAL_NOERR, NULL);
}

static int
TEOV_NotFoundCallback(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int objc = PTR2INT(data[0]);
    Tcl_Obj **objv = (Tcl_Obj **)data[1];
    Namespace *savedNsPtr = (Namespace *)data[2];







|







4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
    TclNRAddCallback(interp, TEOV_NotFoundCallback, INT2PTR(handlerObjc),
	    newObjv, savedNsPtr, NULL);
    return TclNREvalObjv(interp, newObjc, newObjv, TCL_EVAL_NOERR, NULL);
}

static int
TEOV_NotFoundCallback(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int objc = PTR2INT(data[0]);
    Tcl_Obj **objv = (Tcl_Obj **)data[1];
    Namespace *savedNsPtr = (Namespace *)data[2];
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
    Command **cmdPtrPtr,
    Tcl_Obj *commandPtr,
    int objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *) interp;
    Command *cmdPtr = *cmdPtrPtr;
    size_t 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







|







4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
    Command **cmdPtrPtr,
    Tcl_Obj *commandPtr,
    int objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *) interp;
    Command *cmdPtr = *cmdPtrPtr;
    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
	*cmdPtrPtr = NULL;
    }
    return TCL_OK;
}

static int
TEOV_RunLeaveTraces(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int traceCode = TCL_OK;
    int 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;
    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);
	}







|









|







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
	*cmdPtrPtr = NULL;
    }
    return TCL_OK;
}

static int
TEOV_RunLeaveTraces(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    int traceCode = TCL_OK;
    int objc = PTR2INT(data[0]);
    Tcl_Obj *commandPtr = (Tcl_Obj *)data[1];
    Command *cmdPtr = (Command *)data[2];
    Tcl_Obj **objv = (Tcl_Obj **)data[3];
    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
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.
				 * Must be at least 1. */
{
    return TclSubstTokens(interp, tokenPtr, count, /* numLeftPtr */ NULL, 1,
	    NULL, NULL);
}

/*







|







5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
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. */
    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
 */

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
				 * 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
				 * 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 */
    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
				 * 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;
    Tcl_Obj **objv, **objvSpace;
    int *expand, *lines, *lineSpace;

    Tcl_Token *tokenPtr;
    int bytesLeft, expandRequested, code = TCL_OK;
    size_t 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;
				/* 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 **)
	    TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *));
    int *expandStack = (int *)TclStackAlloc(interp, minObjs * sizeof(int));
    int *linesStack = (int *)TclStackAlloc(interp, minObjs * sizeof(int));
				/* TIP #280 Structures for tracking of command
				 * locations. */
    int *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) {
	numBytes = strlen(script);
    }
    Tcl_ResetResult(interp);

    savedVarFramePtr = iPtr->varFramePtr;
    if (flags & TCL_EVAL_GLOBAL) {
	iPtr->varFramePtr = iPtr->rootFramePtr;







|














|





|
|




|














|

|
>

|
|




|









|


|















|







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
 */

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. */
    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. */
    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. */
    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 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 int minObjs = 20;
    Tcl_Obj **objv, **objvSpace;
    int *expand;
    Tcl_Size *lines, *lineSpace;
    Tcl_Token *tokenPtr;
    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;
    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 **)
	    TclStackAlloc(interp, minObjs * sizeof(Tcl_Obj *));
    int *expandStack = (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. */
    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 < 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
	    /*
	     * 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;
	    const char *wordStart = parsePtr->commandStart;
	    int *wordCLNext = clNext;
	    unsigned int objectsNeeded = 0;
	    unsigned int 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));
	    }
	    expandRequested = 0;
	    objv = objvSpace;
	    lines = lineSpace;

	    iPtr->cmdFramePtr = eeFramePtr->nextPtr;
	    for (objectsUsed = 0, tokenPtr = parsePtr->tokenPtr;
		    objectsUsed < numWords;
		    objectsUsed++, tokenPtr += tokenPtr->numComponents+1) {


		/*
		 * 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).
		 */







|

|
|
|








|









>
>







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
	    /*
	     * 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.
	     */

	    Tcl_Size wordLine = line;
	    const char *wordStart = parsePtr->commandStart;
	    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 = (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) {
		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).
		 */
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

		if (code != TCL_OK) {
		    break;
		}
		objv[objectsUsed] = Tcl_GetObjResult(interp);
		Tcl_IncrRefCount(objv[objectsUsed]);
		if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
		    int 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));
			Tcl_DecrRefCount(objv[objectsUsed]);
			break;
		    }
		    expandRequested = 1;
		    expand[objectsUsed] = 1;

		    objectsNeeded += (numElements ? numElements : 1);

		} else {
		    expand[objectsUsed] = 0;





		    objectsNeeded++;



		}


		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;

		if ((numWords > minObjs) || (objectsNeeded > minObjs)) {
		    objv = objvSpace =
			    (Tcl_Obj **)Tcl_Alloc(objectsNeeded * sizeof(Tcl_Obj *));
		    lines = lineSpace = (int *)Tcl_Alloc(objectsNeeded * sizeof(int));
		}

		objectsUsed = 0;
		while (wordIdx--) {
		    if (expand[wordIdx]) {
			int numElements;
			Tcl_Obj **elements, *temp = copy[wordIdx];

			Tcl_ListObjGetElements(NULL, temp, &numElements,
				&elements);
			objectsUsed += numElements;
			while (numElements--) {
			    lines[objIdx] = -1;
			    objv[objIdx--] = elements[numElements];
			    Tcl_IncrRefCount(elements[numElements]);
			}







|









|






|
>


>
>
>
>
>
|
>
>
>

>
















|
|
|




|





|


|







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

		if (code != TCL_OK) {
		    break;
		}
		objv[objectsUsed] = Tcl_GetObjResult(interp);
		Tcl_IncrRefCount(objv[objectsUsed]);
		if (tokenPtr->type == TCL_TOKEN_EXPAND_WORD) {
		    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 %" TCL_SIZE_MODIFIER "d)", objectsUsed));
			Tcl_DecrRefCount(objv[objectsUsed]);
			break;
		    }
		    expandRequested = 1;
		    expand[objectsUsed] = 1;

		    additionalObjsCount = (numElements ? numElements : 1);

		} else {
		    expand[objectsUsed] = 0;
		    additionalObjsCount = 1;
		}

		/* Currently max command words in INT_MAX */
		if (additionalObjsCount > INT_MAX ||
			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;
		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 = (Tcl_Size *)Tcl_Alloc(objectsNeeded * sizeof(Tcl_Size));
		}

		objectsUsed = 0;
		while (wordIdx--) {
		    if (expand[wordIdx]) {
			Tcl_Size numElements;
			Tcl_Obj **elements, *temp = copy[wordIdx];

			TclListObjGetElements(NULL, temp, &numElements,
				&elements);
			objectsUsed += numElements;
			while (numElements--) {
			    lines[objIdx] = -1;
			    objv[objIdx--] = elements[numElements];
			    Tcl_IncrRefCount(elements[numElements]);
			}
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
 *
 * TIP #280
 *----------------------------------------------------------------------
 */

void
TclAdvanceLines(
    int *line,
    const char *start,
    const char *end)
{
    const char *p;

    for (p = start; p < end; p++) {
	if (*p == '\n') {







|







5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
 *
 * TIP #280
 *----------------------------------------------------------------------
 */

void
TclAdvanceLines(
    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
 *
 * TIP #280
 *----------------------------------------------------------------------
 */

void
TclAdvanceContinuations(
    int *line,
    int **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.
     *







|
|







5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
 *
 * TIP #280
 *----------------------------------------------------------------------
 */

void
TclAdvanceContinuations(
    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.
     *
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
    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
	 * something here.
	 */

	if (cfPtr->line[i] < 0) {
	    continue;
	}
	hPtr = Tcl_CreateHashEntry(iPtr->lineLAPtr, objv[i], &isNew);







|
|







5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
    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' 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);
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
{
    Interp *iPtr = (Interp *) interp;
    int i;

    for (i = 1; i < objc; i++) {
	CFWord *cfwPtr;
	Tcl_HashEntry *hPtr =
		Tcl_FindHashEntry(iPtr->lineLAPtr, (char *) objv[i]);

	if (!hPtr) {
	    continue;
	}
	cfwPtr = (CFWord *)Tcl_GetHashValue(hPtr);

	if (cfwPtr->refCount-- > 1) {







|







5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
{
    Interp *iPtr = (Interp *) interp;
    int i;

    for (i = 1; i < objc; i++) {
	CFWord *cfwPtr;
	Tcl_HashEntry *hPtr =
		Tcl_FindHashEntry(iPtr->lineLAPtr, objv[i]);

	if (!hPtr) {
	    continue;
	}
	cfwPtr = (CFWord *)Tcl_GetHashValue(hPtr);

	if (cfwPtr->refCount-- > 1) {
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
void
TclArgumentBCEnter(
    Tcl_Interp *interp,
    Tcl_Obj *objv[],
    int objc,
    void *codePtr,
    CmdFrame *cfPtr,
    int cmd,
    size_t pc)
{
    ExtCmdLoc *eclPtr;
    int word;
    ECL *ePtr;
    CFWordBC *lastPtr = NULL;
    Interp *iPtr = (Interp *) interp;
    Tcl_HashEntry *hePtr =
	    Tcl_FindHashEntry(iPtr->lineBCPtr, (char *) codePtr);

    if (!hePtr) {
	return;
    }
    eclPtr = (ExtCmdLoc *)Tcl_GetHashValue(hePtr);
    ePtr = &eclPtr->loc[cmd];








|
|







|







5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
void
TclArgumentBCEnter(
    Tcl_Interp *interp,
    Tcl_Obj *objv[],
    int objc,
    void *codePtr,
    CmdFrame *cfPtr,
    Tcl_Size cmd,
    Tcl_Size pc)
{
    ExtCmdLoc *eclPtr;
    int word;
    ECL *ePtr;
    CFWordBC *lastPtr = NULL;
    Interp *iPtr = (Interp *) interp;
    Tcl_HashEntry *hePtr =
	    Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr);

    if (!hePtr) {
	return;
    }
    eclPtr = (ExtCmdLoc *)Tcl_GetHashValue(hePtr);
    ePtr = &eclPtr->loc[cmd];

5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
{
    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);
	CFWordBC *xPtr = (CFWordBC *)Tcl_GetHashValue(hPtr);

	if (xPtr != cfwPtr) {
	    Tcl_Panic("TclArgumentBC Enter/Release Mismatch");
	}

	if (cfwPtr->prevPtr) {







|







5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
{
    Interp *iPtr = (Interp *) interp;
    CFWordBC *cfwPtr = (CFWordBC *) cfPtr->litarg;

    while (cfwPtr) {
	CFWordBC *nextPtr = cfwPtr->nextPtr;
	Tcl_HashEntry *hPtr =
		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
    }

    /*
     * First look for location information recorded in the argument
     * stack. That is nearest.
     */

    hPtr = Tcl_FindHashEntry(iPtr->lineLAPtr, (char *) 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);
    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;







|













|







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
    }

    /*
     * First look for location information recorded in the argument
     * stack. That is nearest.
     */

    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, 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;
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
     * 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_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







|







6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
     * 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;
	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
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
	/*
	 * 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;

	/*
	 * 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







|







6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
	/*
	 * 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;
	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
	iPtr->scriptCLLocPtr = saveCLLocPtr;
	return result;
    }
}

static int
TEOEx_ByteCodeCallback(
    ClientData 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;

	    ProcessUnexpectedResult(interp, result);
	    result = TCL_ERROR;
	    script = TclGetStringFromObj(objPtr, &numSrcBytes);
	    Tcl_LogCommandInfo(interp, script, script, numSrcBytes);
	}








|














|







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
	iPtr->scriptCLLocPtr = saveCLLocPtr;
	return result;
    }
}

static int
TEOEx_ByteCodeCallback(
    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;
	    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

    TclDecrRefCount(objPtr);
    return result;
}

static int
TEOEx_ListCallback(
    ClientData 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];







|







6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312

    TclDecrRefCount(objPtr);
    return result;
}

static int
TEOEx_ListCallback(
    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];
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
    } else if (returnCode == TCL_CONTINUE) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"invoked \"continue\" outside of a loop", -1));
    } 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);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
 *







|
|







6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
    } else if (returnCode == TCL_CONTINUE) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"invoked \"continue\" outside of a loop", -1));
    } else {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"command returned bad code: %d", returnCode));
    }
    snprintf(buf, sizeof(buf), "%d", returnCode);
    Tcl_SetErrorCode(interp, "TCL", "UNEXPECTED_RESULT_CODE", buf, (char *)NULL);
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean --
 *
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
				 * expression. */
    Tcl_Obj *objPtr,	/* Expression to evaluate. */
    long *ptr)			/* Where to store long result. */
{
    Tcl_Obj *resultPtr;
    int result, type;
    double d;
    ClientData internalPtr;

    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    if (result != TCL_OK) {
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, resultPtr, &internalPtr, &type)!=TCL_OK) {
	return TCL_ERROR;
    }

    switch (type) {
    case TCL_NUMBER_DOUBLE: {
	mp_int big;








|






|







6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
				 * expression. */
    Tcl_Obj *objPtr,	/* Expression to evaluate. */
    long *ptr)			/* Where to store long result. */
{
    Tcl_Obj *resultPtr;
    int result, type;
    double d;
    void *internalPtr;

    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    if (result != TCL_OK) {
	return TCL_ERROR;
    }

    if (Tcl_GetNumberFromObj(interp, resultPtr, &internalPtr, &type)!=TCL_OK) {
	return TCL_ERROR;
    }

    switch (type) {
    case TCL_NUMBER_DOUBLE: {
	mp_int big;

6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
    Tcl_Interp *interp,		/* Context in which to evaluate the
				 * expression. */
    Tcl_Obj *objPtr,	/* Expression to evaluate. */
    double *ptr)		/* Where to store double result. */
{
    Tcl_Obj *resultPtr;
    int result, type;
    ClientData internalPtr;

    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    if (result != TCL_OK) {
	return TCL_ERROR;
    }

    result = TclGetNumberFromObj(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







|






|







6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
    Tcl_Interp *interp,		/* Context in which to evaluate the
				 * expression. */
    Tcl_Obj *objPtr,	/* Expression to evaluate. */
    double *ptr)		/* Where to store double result. */
{
    Tcl_Obj *resultPtr;
    int result, type;
    void *internalPtr;

    result = Tcl_ExprObj(interp, objPtr, &resultPtr);
    if (result != TCL_OK) {
	return TCL_ERROR;
    }

    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
    return result;
}

int
Tcl_ExprBooleanObj(
    Tcl_Interp *interp,		/* Context in which to evaluate the
				 * expression. */
    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) {







|







6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
    return result;
}

int
Tcl_ExprBooleanObj(
    Tcl_Interp *interp,		/* Context in which to evaluate the
				 * expression. */
    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
 *----------------------------------------------------------------------
 */

int
TclObjInvokeNamespace(
    Tcl_Interp *interp,		/* Interpreter in which command is to be
				 * invoked. */
    int 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. */
{







|







6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
 *----------------------------------------------------------------------
 */

int
TclObjInvokeNamespace(
    Tcl_Interp *interp,		/* Interpreter in which command is to be
				 * invoked. */
    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
 *----------------------------------------------------------------------
 */

int
TclObjInvoke(
    Tcl_Interp *interp,		/* Interpreter in which command is to be
				 * invoked. */
    int 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) {







|







6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
 *----------------------------------------------------------------------
 */

int
TclObjInvoke(
    Tcl_Interp *interp,		/* Interpreter in which command is to be
				 * invoked. */
    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) {
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
    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);
	return TCL_ERROR;
    }
    cmdPtr = (Command *)Tcl_GetHashValue(hPtr);

    /*
     * Avoid the exception-handling brain damage when numLevels == 0
     */







|







6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
    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,
                (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
     */

    return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NORESOLVE, cmdPtr);
}

static int
NRPostInvoke(
    TCL_UNUSED(ClientData *),
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *)interp;

    iPtr->numLevels--;
    return result;







|







6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
     */

    return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NORESOLVE, cmdPtr);
}

static int
NRPostInvoke(
    TCL_UNUSED(void **),
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *)interp;

    iPtr->numLevels--;
    return result;
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

void
Tcl_AppendObjToErrorInfo(
    Tcl_Interp *interp,		/* Interpreter to which error information
				 * pertains. */
    Tcl_Obj *objPtr)		/* Message to record. */
{
    size_t 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);
	}
    }

    /*
     * Now append "message" to the end of errorInfo.
     */








|















|







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

void
Tcl_AppendObjToErrorInfo(
    Tcl_Interp *interp,		/* Interpreter to which error information
				 * pertains. */
    Tcl_Obj *objPtr)		/* Message to record. */
{
    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", (char *)NULL);
	}
    }

    /*
     * Now append "message" to the end of errorInfo.
     */

6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SetRecursionLimit(
    Tcl_Interp *interp,		/* Interpreter whose nesting limit is to be
				 * set. */
    int depth)			/* New value for maximimum depth. */
{
    Interp *iPtr = (Interp *) interp;
    int old;

    old = iPtr->maxNestingDepth;
    if (depth > 0) {
	iPtr->maxNestingDepth = depth;
    }
    return old;
}







|



|


|







6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_SetRecursionLimit(
    Tcl_Interp *interp,		/* Interpreter whose nesting limit is to be
				 * set. */
    Tcl_Size depth)		/* New value for maximum depth. */
{
    Interp *iPtr = (Interp *) interp;
    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
    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);

	if (irPtr) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}
    }
#endif







|







7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
    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_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
    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);

	if (irPtr) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}
    }
#endif







|







7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
    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_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
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;
    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) {
	return TCL_ERROR;
    }

    switch (type) {
    case TCL_NUMBER_NAN:
	Tcl_GetDoubleFromObj(interp, objv[1], &d);
	return TCL_ERROR;







|




















|







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
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. */
{
    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 (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;
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
    }
    return TCL_OK;

  negarg:
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
            "square root of negative argument", -1));
    Tcl_SetErrorCode(interp, "ARITH", "DOMAIN",
	    "domain error: argument not in valid range", NULL);
    return TCL_ERROR;
}

static int
ExprSqrtFunc(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* The interpreter in which to execute the







|







7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
    }
    return TCL_OK;

  negarg:
    Tcl_SetObjResult(interp, Tcl_NewStringObj(
            "square root of negative argument", -1));
    Tcl_SetErrorCode(interp, "ARITH", "DOMAIN",
	    "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
    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);

	if (irPtr) {
	    Tcl_SetObjResult(interp, objv[1]);
	    return TCL_OK;
	}
    }
#endif
    if (code != TCL_OK) {
	return TCL_ERROR;
    }
    if ((d >= 0.0) && TclIsInfinite(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);







|










|







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
    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_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) && 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
	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d)));
    }
    return TCL_OK;
}

static int
ExprUnaryFunc(
    ClientData 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;

    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);

	if (irPtr) {
	    d = irPtr->doubleValue;
	    Tcl_ResetResult(interp);
	    code = TCL_OK;
	}
    }







|


















|







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
	Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sqrt(d)));
    }
    return TCL_OK;
}

static int
ExprUnaryFunc(
    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;

    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_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

static int
CheckDoubleResult(
    Tcl_Interp *interp,
    double dResult)
{
#ifndef ACCEPT_NAN
    if (TclIsNaN(dResult)) {
	TclExprFloatError(interp, dResult);
	return TCL_ERROR;
    }
#endif
    if ((errno == ERANGE) && ((dResult == 0.0) || TclIsInfinite(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
				 * 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;

    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);

	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);

	if (irPtr) {
	    d2 = irPtr->doubleValue;
	    Tcl_ResetResult(interp);
	    code = TCL_OK;
	}
    }







|




|

















|


















|














|







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

static int
CheckDoubleResult(
    Tcl_Interp *interp,
    double dResult)
{
#ifndef ACCEPT_NAN
    if (isnan(dResult)) {
	TclExprFloatError(interp, dResult);
	return TCL_ERROR;
    }
#endif
    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(
    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;

    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_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_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
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;
    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) {
	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;
		const char *bytes = TclGetStringFromObj(objv[1], &numBytes);

		while (numBytes) {
		    if (*bytes == '-') {
			Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
			return TCL_OK;
		    }
		    bytes++; numBytes--;
		}
	    }
	    goto unChanged;
	} else if (l == WIDE_MIN) {









	    if (mp_init_i64(&big, l) != MP_OKAY) {
		return TCL_ERROR;
	    }
	    goto tooLarge;
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-l));
	return TCL_OK;
    }







|








|










|












>
>
>
>
>
>
>
>
>
|







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
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. */
{
    void *ptr;
    int type;
    mp_int big;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    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])) {
		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--;
		}
	    }
	    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;
		}
	    } 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

    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)) {
	    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;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    if (TclGetNumberFromObj(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;







|




















|





|







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

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    if (Tcl_GetDoubleFromObj(interp, objv[1], &dResult) != TCL_OK) {
#ifdef ACCEPT_NAN
	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;
    void *ptr;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }
    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
				 * 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;

    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.
             */








|
>
|







|







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
				 * function. */
    int objc,			/* Actual parameter count. */
    Tcl_Obj *const *objv,	/* Actual parameter vector. */
    int op)			/* Comparison direction */
{
    Tcl_Obj *res;
    double d;
    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 (Tcl_GetNumberFromObj(interp, objv[i], &ptr, &type) != TCL_OK) {
            return TCL_ERROR;
        }
        if (type == TCL_NUMBER_NAN) {
            /*
             * Get the error message for NaN.
             */

7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
	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);

	/*
	 * Make sure 1 <= randSeed <= (2^31) - 2. See below.
	 */

	iPtr->randSeed &= 0x7FFFFFFF;
	if ((iPtr->randSeed == 0) || (iPtr->randSeed == 0x7FFFFFFF)) {
	    iPtr->randSeed ^= 123459876;
	}
    }

    /*
     * Generate the random number using the linear congruential generator
     * defined by the following recurrence:
     *		seed = ( IA * seed ) mod IM







|





|
|
|







7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
	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() + PTR2UINT(Tcl_GetCurrentThread())*4093U;

	/*
	 * Make sure 1 <= randSeed <= (2^31) - 2. See below.
	 */

	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
    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;
    int type;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(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;








|







|







7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
    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;
    void *ptr;
    int type;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	return TCL_ERROR;
    }

    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;

7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
    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;
    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 (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        type = ClassifyDouble(d);







|







|







8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
    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;
    void *ptr;
    int type, result = 0;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	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);
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
    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;
    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 (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        result = (ClassifyDouble(d) == FP_INFINITE);







|







|







8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
    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;
    void *ptr;
    int type, result = 0;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	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);
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
    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;
    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 (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        result = (ClassifyDouble(d) == FP_NAN);







|







|







8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
    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;
    void *ptr;
    int type, result = 1;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	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);
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
    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;
    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 (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        result = (ClassifyDouble(d) == FP_NORMAL);







|







|







8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
    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;
    void *ptr;
    int type, result = 0;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	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);
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
    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;
    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 (type != TCL_NUMBER_NAN) {
        if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
            return TCL_ERROR;
        }
        result = (ClassifyDouble(d) == FP_SUBNORMAL);







|







|







8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
    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;
    void *ptr;
    int type, result = 0;

    if (objc != 2) {
	MathFuncWrongNumArgs(interp, 2, objc, objv);
	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);
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
    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;
    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 (type == TCL_NUMBER_NAN) {
        result = 1;
    } else {
        d = *((const double *) ptr);
        result = (ClassifyDouble(d) == FP_NAN);
    }

    if (TclGetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    }
    if (type == TCL_NUMBER_NAN) {
        result |= 1;
    } else {
        d = *((const double *) ptr);
        result |= (ClassifyDouble(d) == FP_NAN);







|







|









|







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
    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;
    void *ptr;
    int type, result = 0;

    if (objc != 3) {
	MathFuncWrongNumArgs(interp, 3, objc, objv);
	return TCL_ERROR;
    }

    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    }
    if (type == TCL_NUMBER_NAN) {
        result = 1;
    } else {
        d = *((const double *) ptr);
        result = (ClassifyDouble(d) == FP_NAN);
    }

    if (Tcl_GetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    }
    if (type == TCL_NUMBER_NAN) {
        result |= 1;
    } else {
        d = *((const double *) ptr);
        result |= (ClassifyDouble(d) == FP_NAN);
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
    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;
    int type;

    if (objc != 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "floatValue");
	return TCL_ERROR;
    }

    if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    }
    if (type == TCL_NUMBER_NAN) {
        goto gotNaN;
    } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
        return TCL_ERROR;
    }







|







|







8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
    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;
    void *ptr;
    int type;

    if (objc != 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "floatValue");
	return TCL_ERROR;
    }

    if (Tcl_GetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) {
        return TCL_ERROR;
    }
    if (type == TCL_NUMBER_NAN) {
        goto gotNaN;
    } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) {
        return TCL_ERROR;
    }
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
	    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);
}

#ifdef USE_DTRACE
/*
 *----------------------------------------------------------------------
 *
 * DTraceObjCmd --







|







8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
	    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", (char *)NULL);
}

#ifdef USE_DTRACE
/*
 *----------------------------------------------------------------------
 *
 * DTraceObjCmd --
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
 *----------------------------------------------------------------------
 */

void
TclDTraceInfo(
    Tcl_Obj *info,
    const char **args,
    int *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++







|







8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
 *----------------------------------------------------------------------
 */

void
TclDTraceInfo(
    Tcl_Obj *info,
    const char **args,
    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
	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]);
	} else {
	    argsi[i] = 0;
	}
    }
}

/*







|







8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
	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) {
	    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
DTraceCmdReturn(
    ClientData 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);







|







8420
8421
8422
8423
8424
8425
8426
8427
8428
8429
8430
8431
8432
8433
8434
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
DTraceCmdReturn(
    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
 *----------------------------------------------------------------------
 */

int
Tcl_NRCallObjProc(
    Tcl_Interp *interp,
    Tcl_ObjCmdProc *objProc,
    ClientData clientData,
    int 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);
}









































/*
 *----------------------------------------------------------------------
 *
 * 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
 *	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.
 *
 *----------------------------------------------------------------------
 */














































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
				 * 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);

    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,
    Tcl_CmdDeleteProc *deleteProc)
{
    Command *cmdPtr = (Command *)
            TclCreateObjCommandInNs(interp, cmdName, nsPtr, proc, clientData,
                    deleteProc);

    cmdPtr->nreProc = nreProc;







|
|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|




















|







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
 *----------------------------------------------------------------------
 */

int
Tcl_NRCallObjProc(
    Tcl_Interp *interp,
    Tcl_ObjCmdProc *objProc,
    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 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 */
    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);

    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,
    void *clientData,
    Tcl_CmdDeleteProc *deleteProc)
{
    Command *cmdPtr = (Command *)
            TclCreateObjCommandInNs(interp, cmdName, nsPtr, proc, clientData,
                    deleteProc);

    cmdPtr->nreProc = nreProc;
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
    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_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_Obj *const objv[],
    int flags)
{
    return TclNREvalObjv(interp, objc, objv, flags|TCL_EVAL_NOERR,
	    (Command *) cmd);
}








|














|







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
    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. */
    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,
    Tcl_Size objc,
    Tcl_Obj *const objv[],
    int flags)
{
    return TclNREvalObjv(interp, objc, objv, flags|TCL_EVAL_NOERR,
	    (Command *) cmd);
}

8454
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
	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);
	return TCL_ERROR;
    }

    /*
     * Invocation without args just clears a scheduled tailcall; invocation
     * with an argument replaces any previously scheduled tailcall.
     */







|







8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
	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", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Invocation without args just clears a scheduled tailcall; invocation
     * with an argument replaces any previously scheduled tailcall.
     */
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
 *	This NREcallback actually causes the tailcall to be evaluated.
 *
 *----------------------------------------------------------------------
 */

int
TclNRTailcallEval(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *listPtr = (Tcl_Obj *)data[0], *nsObjPtr;
    Tcl_Namespace *nsPtr;
    int objc;
    Tcl_Obj **objv;

    Tcl_ListObjGetElements(interp, listPtr, &objc, &objv);
    nsObjPtr = objv[0];

    if (result == TCL_OK) {
	result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
    }

    if (result != TCL_OK) {







|






|


|







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
 *	This NREcallback actually causes the tailcall to be evaluated.
 *
 *----------------------------------------------------------------------
 */

int
TclNRTailcallEval(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *listPtr = (Tcl_Obj *)data[0], *nsObjPtr;
    Tcl_Namespace *nsPtr;
    Tcl_Size objc;
    Tcl_Obj **objv;

    TclListObjGetElements(interp, listPtr, &objc, &objv);
    nsObjPtr = objv[0];

    if (result == TCL_OK) {
	result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
    }

    if (result != TCL_OK) {
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
    TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
    iPtr->lookupNsPtr = (Namespace *) nsPtr;
    return TclNREvalObjv(interp, objc-1, objv+1, 0, NULL);
}

int
TclNRReleaseValues(
    ClientData 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)
{
    if (!(postProcPtr)) {
	Tcl_Panic("Adding a callback without an objProc?!");
    }
    TclNRAddCallback(interp, postProcPtr, data0, data1, data2, data3);
}








|




















|
|
|
|







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
    TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
    iPtr->lookupNsPtr = (Namespace *) nsPtr;
    return TclNREvalObjv(interp, objc-1, objv+1, 0, NULL);
}

int
TclNRReleaseValues(
    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,
    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
 *----------------------------------------------------------------------
 */

#define iPtr ((Interp *) interp)

int
TclNRYieldObjCmd(
    ClientData 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);
	return TCL_ERROR;
    }

    if (objc == 2) {
	Tcl_SetObjResult(interp, objv[1]);
    }








|














|







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
 *----------------------------------------------------------------------
 */

#define iPtr ((Interp *) interp)

int
TclNRYieldObjCmd(
    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", (char *)NULL);
	return TCL_ERROR;
    }

    if (objc == 2) {
	Tcl_SetObjResult(interp, objv[1]);
    }

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
	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);
	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;
    }

    /*
     * 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);

    /*
     * Add the callback in the caller's env, then instruct TEBC to yield.
     */

    iPtr->execEnvPtr = corPtr->callerEEPtr;

    TclSetTailcall(interp, listPtr);

    iPtr->execEnvPtr = corPtr->eePtr;

    return TclNRYieldObjCmd(INT2PTR(CORO_ACTIVATE_YIELDM), interp, 1, objv);
}

static int
RewindCoroutineCallback(
    ClientData data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    return Tcl_RestoreInterpState(interp, (Tcl_InterpState)data[0]);
}

static int







|







|


















>

>


|




|







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
	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", (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",
		(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);

    /*
     * 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(CORO_ACTIVATE_YIELDM, interp, 1, objv);
}

static int
RewindCoroutineCallback(
    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
    TclNRAddCallback(interp, RewindCoroutineCallback, state,
	    NULL, NULL, NULL);
    return TclNRInterpCoroutine(corPtr, interp, 0, NULL);
}

static void
DeleteCoroutine(
    ClientData 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[],
    Tcl_Interp *interp,
    int result)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    Command *cmdPtr = corPtr->cmdPtr;

    /*







|












|







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
    TclNRAddCallback(interp, RewindCoroutineCallback, state,
	    NULL, NULL, NULL);
    return TclNRInterpCoroutine(corPtr, interp, 0, NULL);
}

static void
DeleteCoroutine(
    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(
    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
    }

    return result;
}

static int
NRCoroutineExitCallback(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    Command *cmdPtr = corPtr->cmdPtr;

    /*







|







9119
9120
9121
9122
9123
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
    }

    return result;
}

static int
NRCoroutineExitCallback(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    Command *cmdPtr = corPtr->cmdPtr;

    /*
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
 *      or inlining.
 *
 *----------------------------------------------------------------------
 */

int
TclNRCoroutineActivateCallback(
    ClientData data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    int type = PTR2INT(data[1]);
    int numLevels, unused;
    int *stackLevel = &unused;

    if (!corPtr->stackLevel) {
        /*
         * -- Coroutine is suspended --
         * Push the callback to restore the caller's context on yield or
         * return.
         */

        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.
         */

        corPtr->stackLevel = stackLevel;
        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;
    } else {
        /*
         * 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 (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->stackLevel = NULL;

        numLevels = iPtr->numLevels;
        iPtr->numLevels = corPtr->auxNumLevels;
        corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels;

        iPtr->execEnvPtr = corPtr->callerEEPtr;
    }

    return TCL_OK;







|




<
<
|

















|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|



>








>


|







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
 *      or inlining.
 *
 *----------------------------------------------------------------------
 */

int
TclNRCoroutineActivateCallback(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];


    void *stackLevel = TclGetCStackPtr();

    if (!corPtr->stackLevel) {
        /*
         * -- Coroutine is suspended --
         * Push the callback to restore the caller's context on yield or
         * return.
         */

        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.
         */

        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;
    } else {
        /*
         * Coroutine is active: yield
         */

        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", -1));
            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");
        }

	corPtr->yieldPtr = NULL;
        corPtr->stackLevel = NULL;

        Tcl_Size numLevels = iPtr->numLevels;
        iPtr->numLevels = corPtr->auxNumLevels;
        corPtr->auxNumLevels = numLevels - corPtr->auxNumLevels;

        iPtr->execEnvPtr = corPtr->callerEEPtr;
    }

    return TCL_OK;
8914
8915
8916
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
8932
 *	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);







|



|







9279
9280
9281
9282
9283
9284
9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
 *	processing of canonical list command in sane environment.
 *
 *----------------------------------------------------------------------
 */

static int
TclNREvalList(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    Tcl_Size objc;
    Tcl_Obj **objv;
    Tcl_Obj *listPtr = (Tcl_Obj *)data[0];

    Tcl_IncrRefCount(listPtr);

    TclMarkTailcall(interp);
    TclNRAddCallback(interp, TclNRReleaseValues, listPtr, NULL, NULL,NULL);
8964
8965
8966
8967
8968
8969
8970
8971
8972
8973
8974
8975
8976
8977
8978
     */

    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;
    }

    /*
     * An active coroutine is "active". Can't tell what it might do in the
     * future.
     */







|







9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
9339
9340
9341
9342
9343
     */

    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]), (char *)NULL);
        return TCL_ERROR;
    }

    /*
     * An active coroutine is "active". Can't tell what it might do in the
     * future.
     */
8994
8995
8996
8997
8998
8999
9000
9001
9002
9003
9004
9005
9006
9007
9008
        return TCL_OK;
    case COROUTINE_ARGUMENTS_ARBITRARY:
        Tcl_SetObjResult(interp, Tcl_NewStringObj("yieldto", -1));
        return TCL_OK;
    default:
        Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "unknown coroutine type", -1));
        Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BAD_TYPE", NULL);
        return TCL_ERROR;
    }
}

/*
 *----------------------------------------------------------------------
 *







|







9359
9360
9361
9362
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
        return TCL_OK;
    case COROUTINE_ARGUMENTS_ARBITRARY:
        Tcl_SetObjResult(interp, Tcl_NewStringObj("yieldto", -1));
        return TCL_OK;
    default:
        Tcl_SetObjResult(interp, Tcl_NewStringObj(
                "unknown coroutine type", -1));
        Tcl_SetErrorCode(interp, "TCL", "COROUTINE", "BAD_TYPE", (char *)NULL);
        return TCL_ERROR;
    }
}

/*
 *----------------------------------------------------------------------
 *
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
     */

    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;
    }
    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");
    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, InjectHandler, corPtr,
            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");
    if (!corPtr) {
        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;
    }

    /*
     * 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, InjectHandler, 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);

    /*
     * 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;

    /*
     * Do the actual stack swap.
     */

    SAVE_CONTEXT(corPtr->caller);







|













<



















|








>
















<
<
<




















|








>




















|
|







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
     */

    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), (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;


    /*
     * 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");
    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", (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);
    iPtr->execEnvPtr = savedEEPtr;

    return TCL_OK;
}

static int
TclNRCoroProbeObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    CoroutineData *corPtr;




    /*
     * 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");
    if (!corPtr) {
        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", (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);
    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);

    /*
     * 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 = &corPtr;
    Tcl_Size numLevels = corPtr->auxNumLevels;
    corPtr->auxNumLevels = iPtr->numLevels;

    /*
     * Do the actual stack swap.
     */

    SAVE_CONTEXT(corPtr->caller);
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
 *      caller context (i.e., where [coroprobe] was run).
 *s
 *----------------------------------------------------------------------
 */

static int
InjectHandler(
    ClientData 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_Obj **objv;

    if (!isProbe) {
        /*
         * 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));
    }

    /*
     * Call the user's script; we're in the right place.
     */

    Tcl_IncrRefCount(listPtr);
    TclMarkTailcall(interp);
    TclNRAddCallback(interp, InjectHandlerPostCall, corPtr, listPtr,
            INT2PTR(nargs), isProbe);
    TclListObjGetElements(NULL, listPtr, &objc, &objv);
    return TclNREvalObjv(interp, objc, objv, 0, NULL);
}

static int
InjectHandlerPostCall(
    ClientData 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];
    int numLevels;

    /*
     * Delete the command words for what we just executed.
     */

    Tcl_DecrRefCount(listPtr);








|





|
|
|



|
|
|

|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
















|





|
|
<







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
 *      caller context (i.e., where [coroprobe] was run).
 *s
 *----------------------------------------------------------------------
 */

static int
InjectHandler(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    Tcl_Obj *listPtr = (Tcl_Obj *)data[1];
    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 (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);
    TclListObjGetElements(NULL, listPtr, &objc, &objv);
    return TclNREvalObjv(interp, objc, objv, 0, NULL);
}

static int
InjectHandlerPostCall(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    CoroutineData *corPtr = (CoroutineData *)data[0];
    Tcl_Obj *listPtr = (Tcl_Obj *)data[1];
    Tcl_Size nargs = PTR2INT(data[2]);
    void *isProbe = data[3];


    /*
     * Delete the command words for what we just executed.
     */

    Tcl_DecrRefCount(listPtr);

9250
9251
9252
9253
9254
9255
9256
9257
9258
9259
9260
9261
9262
9263
9264
    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;
    }
    return result;
}








|







9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
    if (isProbe) {
        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;
}

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
            "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,
    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);
	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;
    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 */
    case COROUTINE_ARGUMENTS_ARBITRARY:
        if (objc > 1) {
            Tcl_SetObjResult(interp, Tcl_NewListObj(objc-1, objv+1));
        }







|


















|










|



















|



|







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
            "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", (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.
     */

    iPtr->execEnvPtr = corPtr->eePtr;
    TclNRAddCallback(interp, TclNREvalList, Tcl_NewListObj(objc-2, objv+2),
	NULL, NULL, NULL);
    iPtr->execEnvPtr = savedEEPtr;

    return TCL_OK;
}

int
TclNRInterpCoroutine(
    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", (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;
    default:
        if (corPtr->nargs + 1 != objc) {
            Tcl_SetObjResult(interp,
                    Tcl_NewStringObj("wrong coro nargs; how did we get here? "
                    "not implemented!", -1));
            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));
        }
9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
    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);
	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);
	return TCL_ERROR;
    }

    /*
     * We ARE creating the coroutine command: allocate the corresponding
     * struct and create the corresponding command.
     */







|






|







9767
9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
    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", (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, (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * We ARE creating the coroutine command: allocate the corresponding
     * struct and create the corresponding command.
     */
9467
9468
9469
9470
9471
9472
9473

9474
9475
9476
9477
9478
9479
9480

    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;


    /*
     * 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);







>







9830
9831
9832
9833
9834
9835
9836
9837
9838
9839
9840
9841
9842
9843
9844

    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);

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
/*
 * 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.
 *
 * 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. */

/*
 * The following flags may be ORed 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
 * 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);
static Tcl_Obj *	ScanNumber(unsigned char *buffer, int type,
			    int flags, Tcl_HashTable **numberCachePtr);
static int		SetByteArrayFromAny(Tcl_Interp *interp,
			    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,
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryScanCmd(ClientData clientData,
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
/* Binary encoding sub-ensemble commands */
static int		BinaryEncodeHex(ClientData clientData,
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryDecodeHex(ClientData clientData,
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryEncode64(ClientData clientData,
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryDecode64(ClientData clientData,
			    Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		BinaryEncodeUu(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		BinaryDecodeUu(ClientData clientData,
			    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',






|
|
















|
|


|










|

















<
<




<


|


|







|
<
<
|
<
<

|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57


58
59
60
61

62
63
64
65
66
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 © 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 -1		/* Use all elements in the argument. */
#define BINARY_NOCOUNT -2	/* No count was specified in format. */

/*
 * 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 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		DupProperByteArrayInternalRep(Tcl_Obj *srcPtr,
			    Tcl_Obj *copyPtr);
static int		FormatNumber(Tcl_Interp *interp, int type,
			    Tcl_Obj *src, unsigned char **cursorPtr);

static void		FreeProperByteArrayInternalRep(Tcl_Obj *objPtr);
static int		GetFormatSpec(const char **formatPtr, char *cmdPtr,
			    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, 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 Tcl_ObjCmdProc	BinaryFormatCmd;


static Tcl_ObjCmdProc	BinaryScanCmd;


/* Binary encoding sub-ensemble commands */
static Tcl_ObjCmdProc	BinaryEncodeHex;


static Tcl_ObjCmdProc	BinaryDecodeHex;


static Tcl_ObjCmdProc	BinaryEncode64;


static Tcl_ObjCmdProc	BinaryDecode64;


static Tcl_ObjCmdProc	BinaryEncodeUu;


static Tcl_ObjCmdProc	BinaryDecodeUu;



/*
 * 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
    { "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
 * 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
 * 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.
 *
 * 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
 * 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.

 */

static const Tcl_ObjType properByteArrayType = {
    "bytearray",
    FreeProperByteArrayInternalRep,
    DupProperByteArrayInternalRep,
    UpdateStringOfByteArray,
    NULL
};

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
				 * array. */
    size_t 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_SIZE(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);
}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	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 */

{
#ifdef TCL_MEM_DEBUG
    return Tcl_DbNewByteArrayObj(bytes, length, "unknown", 0);
#else /* if not TCL_MEM_DEBUG */
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    Tcl_SetByteArrayObj(objPtr, bytes, length);
    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
 *	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. */

    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);
    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_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{
    return Tcl_NewByteArrayObj(bytes, length);
}
#endif /* TCL_MEM_DEBUG */

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_SetByteArrayObj --







|




<
<
<
<


|




|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>







|
<
|
<
<
<
<
<
<










<
<
<
|

|






>

>
>
|








|











|














|
>


|




|




















|













|
>








|







|
|



|







136
137
138
139
140
141
142
143
144
145
146
147




148
149
150
151
152
153
154
155





156



























































157
158
159
160
161
162
163
164
165

166






167
168
169
170
171
172
173
174
175
176



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
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 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.
 *




 * 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.  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.  Tcl string values outside that subset do no represent any valid





 * bytearray value.  Attempts to treat those values as bytearrays will lead



























































 * to errors.  See TIP 568 for how this differs from Tcl 8.
 */

static const Tcl_ObjType properByteArrayType = {
    "bytearray",
    FreeProperByteArrayInternalRep,
    DupProperByteArrayInternalRep,
    UpdateStringOfByteArray,
    NULL,

    TCL_OBJTYPE_V0






};

/*
 * 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 {



    Tcl_Size used;		/* The number of bytes used in the byte
				 * array. */
    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)) )
#define GET_BYTEARRAY(irPtr) ((ByteArray *) (irPtr)->twoPtrValue.ptr1)
#define SET_BYTEARRAY(irPtr, baPtr) \
		(irPtr)->twoPtrValue.ptr1 = (baPtr)

int
TclIsPureByteArray(
    Tcl_Obj * objPtr)
{
    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 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. */
    Tcl_Size numBytes)		/* Number of bytes in the array,
				 * must be >= 0. */
{
#ifdef TCL_MEM_DEBUG
    return Tcl_DbNewByteArrayObj(bytes, numBytes, "unknown", 0);
#else /* if not TCL_MEM_DEBUG */
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    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 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. */
    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, 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. */
    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, 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
 *----------------------------------------------------------------------
 */

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. */
{
    ByteArray *byteArrayPtr;
    Tcl_ObjIntRep ir;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayObj");
    }
    TclInvalidateStringRep(objPtr);


    byteArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(length));
    byteArrayPtr->bad = length;
    byteArrayPtr->used = length;
    byteArrayPtr->allocated = length;

    if ((bytes != NULL) && (length > 0)) {
	memcpy(byteArrayPtr->bytes, bytes, length);
    }
    SET_BYTEARRAY(&ir, byteArrayPtr);

    Tcl_StoreIntRep(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
 *	interp (if not NULL).
 *
 * Results:
 *	Pointer to array of bytes, or NULL. representing the ByteArray object.
 *	Writes number of bytes in array to *lengthPtr.
 *
 *----------------------------------------------------------------------
 */




























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. */
{
    ByteArray *baPtr;
    const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &properByteArrayType);

    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);
		nonbyte = Tcl_UtfAtIndex(Tcl_GetString(objPtr), baPtr->bad);
		TclUtfToUCS4(nonbyte, &ucs4);

		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);

    if (lengthPtr != NULL) {
	*lengthPtr = baPtr->used;
    }
    return baPtr->bytes;
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

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);

    if (bytes == NULL) {
	ByteArray *baPtr;
	const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);

	assert(irPtr != 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;
	}
    }
    return bytes;
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetByteArrayLength --
 *
 *	This procedure changes the length of the byte array for this object.







|
|
|


|






>
|
<
|
|

|
|



|









|



|
|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|
|

|
<
|
<
<
<
<
<
<
<

<
|
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
|
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<


|




>







312
313
314
315
316
317
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 numBytes > 0. */
    Tcl_Size numBytes)		/* Number of bytes in the array,
				 * must be >= 0 */
{
    ByteArray *byteArrayPtr;
    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(numBytes));

    byteArrayPtr->used = numBytes;
    byteArrayPtr->allocated = numBytes;

    if ((bytes != NULL) && (numBytes > 0)) {
	memcpy(byteArrayPtr->bytes, bytes, numBytes);
    }
    SET_BYTEARRAY(&ir, byteArrayPtr);

    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 failure, return NULL and record error message and code in
 *	interp (if not NULL).
 *
 * Results:
 *	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 */
    void *numBytesPtr)		/* If non-NULL, write the number of bytes
				 * in the array here */
{
    Tcl_Size numBytes = 0;

    unsigned char *bytes = Tcl_GetBytesFromObj(interp, objPtr, &numBytes);









    if (bytes && numBytesPtr) {


	if (numBytes > INT_MAX) {









	    /* Caller asked for numBytes to be written to an int, but the





	     * value is outside the int range. */

















	    if (interp) {








		Tcl_SetObjResult(interp, Tcl_NewStringObj(



			"byte sequence length exceeds INT_MAX", -1));

		Tcl_SetErrorCode(interp, "TCL", "API", "OUTDATED", (void *)NULL);



	    }










	    return NULL;
	} else {
	    *(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
 *
 *----------------------------------------------------------------------
 */

unsigned char *
Tcl_SetByteArrayLength(
    Tcl_Obj *objPtr,		/* The ByteArray object. */
    size_t length)		/* New length for internal byte array. */

{
    ByteArray *byteArrayPtr;
    Tcl_ObjIntRep *irPtr;


    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength");
    }

    irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
    if (irPtr == NULL) {
	irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);
	if (irPtr == NULL) {
	    SetByteArrayFromAny(NULL, objPtr);
	    irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
	    if (irPtr == NULL) {
		irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);
	    }
	}

    }

    byteArrayPtr = GET_BYTEARRAY(irPtr);
    if (length > byteArrayPtr->allocated) {
	byteArrayPtr = (ByteArray *)Tcl_Realloc(byteArrayPtr, BYTEARRAY_SIZE(length));

	byteArrayPtr->allocated = length;
	SET_BYTEARRAY(irPtr, byteArrayPtr);
    }
    TclInvalidateStringRep(objPtr);




























    objPtr->typePtr = &properByteArrayType;





























    byteArrayPtr->bad = length;







    byteArrayPtr->used = length;












    return byteArrayPtr->bytes;
}












/*
 *----------------------------------------------------------------------
 *
 * SetByteArrayFromAny --
 *
 *	Generate the ByteArray internal rep from the string rep.
 *
 * Results:
 *	The return value is always TCL_OK.
 *
 * Side effects:
 *	A ByteArray object is stored as the internal rep of objPtr.
 *
 *----------------------------------------------------------------------
 */

static int
SetByteArrayFromAny(
    TCL_UNUSED(Tcl_Interp *),

    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;

    if (TclHasIntRep(objPtr, &properByteArrayType)) {
	return TCL_OK;
    }
    if (TclHasIntRep(objPtr, &tclByteArrayType)) {
	return TCL_OK;
    }

    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);
    } 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)));
}

/*
 *----------------------------------------------------------------------
 *
 * 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;
    ByteArray *srcArrayPtr, *copyArrayPtr;
    Tcl_ObjIntRep ir;

    srcArrayPtr = GET_BYTEARRAY(TclFetchIntRep(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);
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfByteArray --
 *







|
>


|

>




|

<
<
|
<
|
<
|
<
>



|
|
>
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>









|


|






|
>


<
<
<
<

|

<
<
<
|
|


<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
|
<
<
<
<
<




















<
<
<
<
<
<
<




|




















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|

|

|



<





|







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
 *
 *----------------------------------------------------------------------
 */

unsigned char *
Tcl_SetByteArrayLength(
    Tcl_Obj *objPtr,		/* The ByteArray object. */
    Tcl_Size numBytes)		/* Number of bytes in resized array
                                 * Must be >= 0 */
{
    ByteArray *byteArrayPtr;
    Tcl_ObjInternalRep *irPtr;

    assert(numBytes >= 0);
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength");
    }

    irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    if (irPtr == NULL) {


	if (TCL_ERROR == SetByteArrayFromAny(NULL, numBytes, objPtr)) {

	    return NULL;

	}

	irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    }

    byteArrayPtr = GET_BYTEARRAY(irPtr);
    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
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", (void *)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:
 *	Tcl return code indicating OK or ERROR.
 *
 * Side effects:
 *	A ByteArray struct may be stored as the internal rep of objPtr.
 *
 *----------------------------------------------------------------------
 */

static int
SetByteArrayFromAny(
    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. */
{




    ByteArray *byteArrayPtr;
    Tcl_ObjInternalRep ir;




    if (0 == MakeByteArray(interp, objPtr, limit, 1, &byteArrayPtr)) {
	return TCL_ERROR;
    }














    SET_BYTEARRAY(&ir, byteArrayPtr);





    Tcl_StoreInternalRep(objPtr, &properByteArrayType, &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
FreeProperByteArrayInternalRep(
    Tcl_Obj *objPtr)		/* Object with internal rep to free. */
{
    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






















DupProperByteArrayInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    Tcl_Size length;
    ByteArray *srcArrayPtr, *copyArrayPtr;
    Tcl_ObjInternalRep ir;

    srcArrayPtr = GET_BYTEARRAY(TclFetchInternalRep(srcPtr, &properByteArrayType));
    length = srcArrayPtr->used;

    copyArrayPtr = (ByteArray *)Tcl_Alloc(BYTEARRAY_SIZE(length));

    copyArrayPtr->used = length;
    copyArrayPtr->allocated = length;
    memcpy(copyArrayPtr->bytes, srcArrayPtr->bytes, length);

    SET_BYTEARRAY(&ir, copyArrayPtr);
    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
 */

static void
UpdateStringOfByteArray(
    Tcl_Obj *objPtr)		/* ByteArray object whose string rep to
				 * update. */
{
    const Tcl_ObjIntRep *irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
    ByteArray *byteArrayPtr = GET_BYTEARRAY(irPtr);
    unsigned char *src = byteArrayPtr->bytes;
    size_t i, length = byteArrayPtr->used;
    size_t size = length;

    /*
     * How much space will string rep need?
     */

    for (i = 0; i < length; i++) {
	if ((src[i] == 0) || (src[i] > 127)) {







|


|
|







673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
 */

static void
UpdateStringOfByteArray(
    Tcl_Obj *objPtr)		/* ByteArray object whose string rep to
				 * update. */
{
    const Tcl_ObjInternalRep *irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    ByteArray *byteArrayPtr = GET_BYTEARRAY(irPtr);
    unsigned char *src = byteArrayPtr->bytes;
    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
    } 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 --







<







700
701
702
703
704
705
706

707
708
709
710
711
712
713
    } else {
	char *dst = Tcl_InitStringRep(objPtr, NULL, size);

	TclOOM(dst, size);
	for (i = 0; i < length; i++) {
	    dst += Tcl_UniCharToUtf(src[i], dst);
	}

    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *----------------------------------------------------------------------
 */

void
TclAppendBytesToByteArray(
    Tcl_Obj *objPtr,
    const unsigned char *bytes,
    size_t len)
{
    ByteArray *byteArrayPtr;
    size_t needed;
    Tcl_ObjIntRep *irPtr;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray");
    }
    if (len == TCL_INDEX_NONE) {
	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);
    if (irPtr == NULL) {
	irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);
	if (irPtr == NULL) {
	    SetByteArrayFromAny(NULL, objPtr);
	    irPtr = TclFetchIntRep(objPtr, &properByteArrayType);
	    if (irPtr == NULL) {
		irPtr = TclFetchIntRep(objPtr, &tclByteArrayType);

	    }
	}

    }
    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) {
	ByteArray *ptr = NULL;
	size_t attempt;

	if (needed <= INT_MAX/2) {
	    /*
	     * Try to allocate double the total space that is needed.
	     */

	    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;
	    size_t extra = len + TCL_MIN_GROWTH;
	    size_t growth = (extra > limit) ? limit : extra;

	    attempt = needed + growth;
	    ptr = (ByteArray *)Tcl_AttemptRealloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
	}
	if (ptr == NULL) {
	    /*
	     * Last chance: Try to allocate exactly what is needed.
	     */

	    attempt = needed;
	    ptr = (ByteArray *)Tcl_Realloc(byteArrayPtr, BYTEARRAY_SIZE(attempt));
	}

	byteArrayPtr = ptr;

	byteArrayPtr->allocated = attempt;
	SET_BYTEARRAY(irPtr, byteArrayPtr);
    }

    if (bytes) {
	memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, len);
    }
    byteArrayPtr->used += len;
    TclInvalidateStringRep(objPtr);
    objPtr->typePtr = &properByteArrayType;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitBinaryCmd --
 *







|


|
|




|











|

<
<
|
<
<
<
>
|
<
>



<
<
<
<
<




|
<
<
|
<
<
<
<
|
<
<
|
<
<
<
<
|
|
<
<
|
<
|
<
<
<
<
<
|
|
<
<
>
|
>
|








<







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
 *----------------------------------------------------------------------
 */

void
TclAppendBytesToByteArray(
    Tcl_Obj *objPtr,
    const unsigned char *bytes,
    Tcl_Size len)
{
    ByteArray *byteArrayPtr;
    Tcl_Size needed;
    Tcl_ObjInternalRep *irPtr;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray");
    }
    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 = TclFetchInternalRep(objPtr, &properByteArrayType);
    if (irPtr == NULL) {


	if (TCL_ERROR == SetByteArrayFromAny(NULL, TCL_INDEX_NONE, objPtr)) {



	    Tcl_Panic("attempt to append bytes to non-bytearray");
	}

	irPtr = TclFetchInternalRep(objPtr, &properByteArrayType);
    }
    byteArrayPtr = GET_BYTEARRAY(irPtr);






    /*
     * If we need to, resize the allocated space in the byte array.
     */

    if ((BYTEARRAY_MAX_LEN - byteArrayPtr->used) < len) {


	/* Will wrap around !! */




	Tcl_Panic("max size of a byte array exceeded");


    }




    needed = byteArrayPtr->used + len;
    if (needed > byteArrayPtr->allocated) {


	Tcl_Size newCapacity;

	byteArrayPtr =





	    (ByteArray *)TclReallocElemsEx(byteArrayPtr,
					   needed,


					   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);

}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
BinaryFormatCmd(
    TCL_UNUSED(ClientData),
    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
				 * 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;
    size_t length;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "formatString ?arg ...?");
	return TCL_ERROR;
    }

    /*







|








|











|
<







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
BinaryFormatCmd(
    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. */
    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;
    Tcl_Size offset, size, 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
	     * of bytes in a single argument.
	     */

	    if (arg >= objc) {
		goto badIndex;
	    }
	    if (count == BINARY_ALL) {
		(void)TclGetByteArrayFromObj(objv[arg], &count);


	    } else if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    arg++;
	    if (cmd == 'a' || cmd == 'A') {
		offset += count;
	    } else if (cmd == 'b' || cmd == 'B') {







|
>
>







891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
	     * of bytes in a single argument.
	     */

	    if (arg >= objc) {
		goto badIndex;
	    }
	    if (count == BINARY_ALL) {
		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
	     * non-list value.
	     */

	    if (count == BINARY_NOCOUNT) {
		arg++;
		count = 1;
	    } else {
		int listc;
		Tcl_Obj **listv;

		/*
		 * The macro evals its args more than once: avoid arg++
		 */

		if (TclListObjGetElements(interp, objv[arg], &listc,
			&listv) != TCL_OK) {
		    return TCL_ERROR;
		}
		arg++;

		if (count == BINARY_ALL) {
		    count = listc;
		} else if (count > (size_t)listc) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "number of elements in list does not match count",
			    -1));
		    return TCL_ERROR;
		}





	    }
	    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)) {
		count = offset;
	    }
	    if (offset > (int)length) {
		length = offset;
	    }
	    offset -= count;
	    break;
	case '@':
	    if (offset > (int)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) {
	length = offset;
    }
    if (length == 0) {
	return TCL_OK;
    }

    /*
     * Prepare the result object by preallocating the caclulated number of
     * bytes and filling with nulls.
     */

    TclNewObj(resultPtr);
    buffer = Tcl_SetByteArrayLength(resultPtr, length);
    memset(buffer, 0, length);








|






|
<


<



|





>
>
>
>
>


















|


|





|















|







|







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
	     * non-list value.
	     */

	    if (count == BINARY_NOCOUNT) {
		arg++;
		count = 1;
	    } else {
		Tcl_Size listc;
		Tcl_Obj **listv;

		/*
		 * The macro evals its args more than once: avoid arg++
		 */

		if (TclListObjLength(interp, objv[arg], &listc) != TCL_OK) {

		    return TCL_ERROR;
		}


		if (count == BINARY_ALL) {
		    count = 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 > offset) || (count == BINARY_ALL)) {
		count = offset;
	    }
	    if (offset > length) {
		length = offset;
	    }
	    offset -= count;
	    break;
	case '@':
	    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 > length) {
	length = offset;
    }
    if (length == 0) {
	return TCL_OK;
    }

    /*
     * 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
	    continue;
	}
	switch (cmd) {
	case 'a':
	case 'A': {
	    char pad = (char) (cmd == 'a' ? '\0' : ' ');
	    unsigned char *bytes;


	    bytes = TclGetByteArrayFromObj(objv[arg], &length);
	    arg++;
	    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;

	    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++) {
		    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++) {
		    value >>= 1;
		    if (str[offset] == '1') {
			value |= 128;
		    } else if (str[offset] != '0') {
			errorValue = str;
			Tcl_DecrRefCount(resultPtr);
			goto badValue;







>

|
|












>




















|














|







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
	    continue;
	}
	switch (cmd) {
	case 'a':
	case 'A': {
	    char pad = (char) (cmd == 'a' ? '\0' : ' ');
	    unsigned char *bytes;
	    Tcl_Obj *copy = TclNarrowToBytes(objv[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; 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; 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
	    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++) {
		    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++) {
		    value >>= 4;

		    if (!isxdigit(UCHAR(str[offset]))) {     /* INTL: digit */
			errorValue = str;
			Tcl_DecrRefCount(resultPtr);
			goto badValue;
		    }







|




















|







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
	    last = cursor + ((count + 1) / 2);
	    if (count > length) {
		count = length;
	    }
	    value = 0;
	    errorString = "hexadecimal";
	    if (cmd == 'H') {
		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; 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
	case 'W':
	case 'r':
	case 'R':
	case 'd':
	case 'q':
	case 'Q':
	case 'f': {
	    int 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++) {
		if (FormatNumber(interp, cmd, listv[i], &cursor) != TCL_OK) {
		    Tcl_DecrRefCount(resultPtr);
		    return TCL_ERROR;
		}
	    }
	    break;
	}







|


















|







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
	case 'W':
	case 'r':
	case 'R':
	case 'd':
	case 'q':
	case 'Q':
	case 'f': {
	    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; 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
	case 'X':
	    if (cursor > maxPos) {
		maxPos = cursor;
	    }
	    if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    if ((count == BINARY_ALL) || (count > (size_t)(cursor - buffer))) {
		cursor = buffer;
	    } else {
		cursor -= count;
	    }
	    break;
	case '@':
	    if (cursor > maxPos) {







|







1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
	case 'X':
	    if (cursor > maxPos) {
		maxPos = cursor;
	    }
	    if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    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
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
BinaryScanCmd(
    TCL_UNUSED(ClientData),
    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
				 * 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;
    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;




    }
    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': {
	    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) {
		    goto done;
		}
	    }

	    src = buffer + offset;
	    size = count;

	    /*

	     * Trim trailing nulls and spaces, if necessary.
	     */

	    if (cmd == 'A') {







		while (size > 0) {
		    if (src[size - 1] != '\0' && src[size - 1] != ' ') {
			break;
		    }
		    size--;
		}
	    }







|

|








|








|
<









>
>
>
>



<











>
|












|








>
|


|
>
>
>
>
>
>
>







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
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
BinaryScanCmd(
    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. */
    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;
    Tcl_Size offset, size, length = 0, i;


    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);

    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 '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)) {
		    goto done;
		}
	    }

	    src = buffer + offset;
	    size = count;

	    /*
	     * Apply C string semantics or trim trailing
	     * nulls and spaces, if necessary.
	     */

	    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
	    }
	    if (count == BINARY_ALL) {
		count = (length - offset) * 8;
	    } else {
		if (count == BINARY_NOCOUNT) {
		    count = 1;
		}
		if (count > (size_t)(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++) {
		    if (i % 8) {
			value >>= 1;
		    } else {
			value = *src++;
		    }
		    *dest++ = (char) ((value & 1) ? '1' : '0');
		}
	    } else {
		for (i = 0; (size_t)i < count; i++) {
		    if (i % 8) {
			value <<= 1;
		    } else {
			value = *src++;
		    }
		    *dest++ = (char) ((value & 0x80) ? '1' : '0');
		}







|









|








|







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
	    }
	    if (count == BINARY_ALL) {
		count = (length - offset) * 8;
	    } else {
		if (count == BINARY_NOCOUNT) {
		    count = 1;
		}
		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; i < count; i++) {
		    if (i % 8) {
			value >>= 1;
		    } else {
			value = *src++;
		    }
		    *dest++ = (char) ((value & 1) ? '1' : '0');
		}
	    } else {
		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
	    }
	    src = buffer + offset;
	    TclNewObj(valuePtr);
	    Tcl_SetObjLength(valuePtr, count);
	    dest = TclGetString(valuePtr);

	    if (cmd == 'h') {
		for (i = 0; (size_t)i < count; i++) {
		    if (i % 2) {
			value >>= 4;
		    } else {
			value = *src++;
		    }
		    *dest++ = hexdigit[value & 0xF];
		}
	    } else {
		for (i = 0; (size_t)i < count; i++) {
		    if (i % 2) {
			value <<= 4;
		    } else {
			value = *src++;
		    }
		    *dest++ = hexdigit[(value >> 4) & 0xF];
		}







|








|







1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
	    }
	    src = buffer + offset;
	    TclNewObj(valuePtr);
	    Tcl_SetObjLength(valuePtr, count);
	    dest = TclGetString(valuePtr);

	    if (cmd == 'h') {
		for (i = 0; i < count; i++) {
		    if (i % 2) {
			value >>= 4;
		    } else {
			value = *src++;
		    }
		    *dest++ = hexdigit[value & 0xF];
		}
	    } else {
		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

	scanNumber:
	    if (arg >= objc) {
		DeleteScanNumberCache(numberCachePtr);
		goto badIndex;
	    }
	    if (count == BINARY_NOCOUNT) {
		if ((length - offset) < (size_t)size) {
		    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++) {
		    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)) {
		offset = length;
	    } else {
		offset += count;
	    }
	    break;
	case 'X':
	    if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    if ((count == BINARY_ALL) || (count > (size_t)offset)) {
		offset = 0;
	    } else {
		offset -= count;
	    }
	    break;
	case '@':
	    if (count == BINARY_NOCOUNT) {







|














|




















|









|







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

	scanNumber:
	    if (arg >= objc) {
		DeleteScanNumberCache(numberCachePtr);
		goto badIndex;
	    }
	    if (count == BINARY_NOCOUNT) {
		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; 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))) {
		offset = length;
	    } else {
		offset += count;
	    }
	    break;
	case 'X':
	    if (count == BINARY_NOCOUNT) {
		count = 1;
	    }
	    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
 *----------------------------------------------------------------------
 */

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. */
    int *flagsPtr)		/* Pointer to field flags */
{
    /*
     * Skip any leading blanks.
     */

    while (**formatPtr == ' ') {







|







1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
 *----------------------------------------------------------------------
 */

static int
GetFormatSpec(
    const char **formatPtr,	/* Pointer to format string. */
    char *cmdPtr,		/* Pointer to location of command char. */
    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
	(*formatPtr)++;
	*flagsPtr |= BINARY_UNSIGNED;
    }
    if (**formatPtr == '*') {
	(*formatPtr)++;
	*countPtr = BINARY_ALL;
    } else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */
	unsigned long int count;

	errno = 0;
	count = strtoul(*formatPtr, (char **) formatPtr, 10);
	if (errno || (count > (unsigned long) INT_MAX)) {
	    *countPtr = INT_MAX;
	} else {
	    *countPtr = (int) 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.
 *	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.
 *







|


|
|
|

|














|







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
	(*formatPtr)++;
	*flagsPtr |= BINARY_UNSIGNED;
    }
    if (**formatPtr == '*') {
	(*formatPtr)++;
	*countPtr = BINARY_ALL;
    } else if (isdigit(UCHAR(**formatPtr))) { /* INTL: digit */
	unsigned long long count;

	errno = 0;
	count = strtoull(*formatPtr, (char **) formatPtr, 10);
	if (errno || (count > TCL_SIZE_MAX)) {
	    *countPtr = TCL_SIZE_MAX;
	} else {
	    *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 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
	/*
	 * 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);
	    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);

	    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) {



	    fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX;

	} else {
	    fvalue = (float) dvalue;
	}
	CopyNumber(&fvalue, *cursorPtr, sizeof(float), type);
	*cursorPtr += sizeof(float);
	return TCL_OK;








|



















|














>
>
>

>







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
	/*
	 * 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_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_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
    case 'i':
    case 'I':
    case 'n':
	if (NeedReversing(type)) {
	    value = (long) (buffer[0]
		    + (buffer[1] << 8)
		    + (buffer[2] << 16)
		    + (((long)buffer[3]) << 24));
	} else {
	    value = (long) (buffer[3]
		    + (buffer[2] << 8)
		    + (buffer[1] << 16)
		    + (((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);
	}

    returnNumericObject:
	if (*numberCachePtrPtr == NULL) {
	    return Tcl_NewWideIntObj(value);
	} else {
	    Tcl_HashTable *tablePtr = *numberCachePtrPtr;







|




|













|
|
|







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
    case 'i':
    case 'I':
    case 'n':
	if (NeedReversing(type)) {
	    value = (long) (buffer[0]
		    + (buffer[1] << 8)
		    + (buffer[2] << 16)
		    + (((unsigned long)buffer[3]) << 24));
	} else {
	    value = (long) (buffer[3]
		    + (buffer[2] << 8)
		    + (buffer[1] << 16)
		    + (((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 & (1U << 31)) && (value > 0)) {
	    value -= (1U << 31);
	    value -= (1U << 31);
	}

    returnNumericObject:
	if (*numberCachePtrPtr == NULL) {
	    return Tcl_NewWideIntObj(value);
	} else {
	    Tcl_HashTable *tablePtr = *numberCachePtrPtr;
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
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryEncodeHex(
    TCL_UNUSED(ClientData),
    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;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "data");
	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;







|







|






>
>
>
>
>

<







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
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryEncodeHex(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj = NULL;
    unsigned char *data = NULL;
    unsigned char *cursor = NULL;
    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);

    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
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryDecodeHex(
    TCL_UNUSED(ClientData),
    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;
    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;







|








|







2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryDecodeHex(
    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;
    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
	case OPT_STRICT:
	    strict = 1;
	    break;
	}
    }

    TclNewObj(resultObj);
    data = TclGetBytesFromObj(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 + 1) / 2;
    begin = cursor = Tcl_SetByteArrayLength(resultObj, size);
    while (data < dataend) {
	value = 0;







|


|







2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
	case OPT_STRICT:
	    strict = 1;
	    break;
	}
    }

    TclNewObj(resultObj);
    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 + 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
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;

  badChar:
    if (pure) {
	ucs4 = c;
    } else {
	TclUtfToUCS4((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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * BinaryEncode64 --







|





|







2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;

  badChar:
    if (pure) {
	ucs4 = c;
    } else {
	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", (void *)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
	if (cursor > limit) {				\
	    Tcl_Panic("limit hit");			\
	}						\
    } while (0)

static int
BinaryEncode64(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj;
    unsigned char *data, *limit;
    int maxlen = 0;
    const char *wrapchar = "\n";
    size_t wrapcharlen = 1;
    int i, index, size, outindex = 0, purewrap = 1;
    size_t offset, 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) {
		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);
		return TCL_ERROR;
	    }
	    break;
	case OPT_WRAPCHAR:
	    wrapchar = (const char *)TclGetBytesFromObj(NULL,
		    objv[i + 1], &wrapcharlen);
	    if (wrapchar == NULL) {
		purewrap = 0;
		wrapchar = TclGetStringFromObj(objv[i + 1], &wrapcharlen);
	    }
	    break;
	}
    }
    if (wrapcharlen == 0) {
	maxlen = 0;
    }





    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));








|






|

|
|
|















|






|




|












>
>
>
>

<







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
	if (cursor > limit) {				\
	    Tcl_Panic("limit hit");			\
	}						\
    } while (0)

static int
BinaryEncode64(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj;
    unsigned char *data, *limit;
    Tcl_WideInt maxlen = 0;
    const char *wrapchar = "\n";
    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 (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", (void *)NULL);
		return TCL_ERROR;
	    }
	    break;
	case OPT_WRAPCHAR:
	    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);

    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
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryEncodeUu(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj;
    unsigned char *data, *start, *cursor;
    int rawLength, n, i, bits, index;

    int lineLength = 61;
    const unsigned char SingleNewline[] = { UCHAR('\n') };
    const unsigned char *wrapchar = SingleNewline;
    size_t j, 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;







|






|
>



|







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
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryEncodeUu(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *resultObj;
    unsigned char *data, *start, *cursor;
    int i, bits, index;
    unsigned int n;
    int lineLength = 61;
    const unsigned char SingleNewline[] = { UCHAR('\n') };
    const unsigned char *wrapchar = 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
		    &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);
		return TCL_ERROR;
	    }
	    lineLength = ((lineLength - 1) & -4) + 1; /* 5, 9, 13 ... */
	    break;
	case OPT_WRAPCHAR:
	    wrapchar = (const unsigned char *) TclGetStringFromObj(
		    objv[i + 1], &wrapcharlen);
	    {
		const unsigned char *p = wrapchar;
		size_t 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);
			    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);




    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;

	if (lineLen > rawLength) {
	    lineLen = rawLength;
	}
	*cursor++ = UueDigits[lineLen];
	for (i = 0 ; i < lineLen ; i++) {
	    n <<= 8;







|





|



|


















|
















<

|
>
>
>
>














|







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
		    &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", (void *)NULL);
		return TCL_ERROR;
	    }
	    lineLength = ((lineLength - 1) & -4) + 1; /* 5, 9, 13 ... */
	    break;
	case OPT_WRAPCHAR:
	    wrapchar = (const unsigned char *)TclGetStringFromObj(
		    objv[i + 1], &wrapcharlen);
	    {
		const unsigned char *p = wrapchar;
		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", (void *)NULL);
			    return TCL_ERROR;
		    }
		}
		if (numBytes) {
		    goto badwrap;
		}
	    }
	    break;
	}
    }

    /*
     * Allocate the buffer. This is a little bit too long, but is "good
     * enough".
     */


    offset = 0;
    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) {
	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
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryDecodeUu(
    TCL_UNUSED(ClientData),
    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;
    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");







|








|







2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryDecodeUu(
    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;
    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
	case OPT_STRICT:
	    strict = 1;
	    break;
	}
    }

    TclNewObj(resultObj);
    data = TclGetBytesFromObj(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;







|







2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
	case OPT_STRICT:
	    strict = 1;
	    break;
	}
    }

    TclNewObj(resultObj);
    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
    }
    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);
    TclDecrRefCount(resultObj);
    return TCL_ERROR;

  badUu:
    if (pure) {
	ucs4 = c;
    } else {
	TclUtfToUCS4((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);
    TclDecrRefCount(resultObj);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *







|







|




|







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
    }
    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", (void *)NULL);
    TclDecrRefCount(resultObj);
    return TCL_ERROR;

  badUu:
    if (pure) {
	ucs4 = c;
    } else {
	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", (void *)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
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryDecode64(
    TCL_UNUSED(ClientData),
    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;
    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;







|










|







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
 *	None
 *
 *----------------------------------------------------------------------
 */

static int
BinaryDecode64(
    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;
    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
	case OPT_STRICT:
	    strict = 1;
	    break;
	}
    }

    TclNewObj(resultObj);
    data = TclGetBytesFromObj(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;







|







3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
	case OPT_STRICT:
	    strict = 1;
	    break;
	}
    }

    TclNewObj(resultObj);
    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
	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);
    }

    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);
    TclDecrRefCount(resultObj);
    return TCL_ERROR;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|





|











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
	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 */
	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", (void *)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
/*
 * 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.
 *
 * 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"


#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
				 * needed for actual tag. This must be the
				 * last field in the structure. */
} MemTag;

#define TAG_SIZE(bytesInString) ((offsetof(MemTag, string) + 1) + 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







|
|
|








>




















|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 © 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[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) + 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
    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
				 * of this field will be larger than one. */
};

static struct mem_header *allocHead = NULL;  /* List of allocated structures */

#define GUARD_VALUE  0141

/*
 * 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 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 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







|





|

















|
|


|
|
|
|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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[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  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 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 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
 * 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







<
<
<
<
<
<
<
<
<
<
<
<
<







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;














/*
 *----------------------------------------------------------------------
 *
 * 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
 *	Display the global memory management statistics.
 *
 *----------------------------------------------------------------------
 */

int
TclDumpMemoryInfo(
    ClientData clientData,
    int flags)
{
    char buf[1024];

    if (clientData == NULL) {
        return 0;
    }
    sprintf(buf,
	    "total mallocs             %10u\n"
	    "total frees               %10u\n"
	    "current packets allocated %10u\n"
	    "current bytes allocated   %10" TCL_Z_MODIFIER "u\n"
	    "maximum packets allocated %10u\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);







|







|
|
|
|

|







161
162
163
164
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(
    void *clientData,
    int flags)
{
    char buf[1024];

    if (clientData == NULL) {
        return 0;
    }
    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 %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
	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);
	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 */
	}







|







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];
	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

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	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__.







|







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, 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
    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)) {
	result = (struct mem_header *) TclpAlloc(size +
		sizeof(struct mem_header) + 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);
    } else {
	memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
	memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
    }
    if (!ckallocInit) {
	TclInitDbCkalloc();
    }







|

|















|







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 <= (size_t)-2 - offsetof(struct mem_header, body) - HIGH_GUARD_SIZE) {
	result = (struct mem_header *) TclpAlloc(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,
		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
	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",
		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);
    }

    current_malloc_packets++;
    if (current_malloc_packets > maximum_malloc_packets) {
	maximum_malloc_packets = current_malloc_packets;
    }
    current_bytes_malloced += size;







|














|







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 (%" 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 (%" 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
    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)) {
	result = (struct mem_header *) TclpAlloc(size +
		sizeof(struct mem_header) + 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);
    } else {
	memset(result->low_guard, GUARD_VALUE, LOW_GUARD_SIZE);
	memset(result->body + size, GUARD_VALUE, HIGH_GUARD_SIZE);
    }
    if (!ckallocInit) {
	TclInitDbCkalloc();
    }







|

|














|







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 <= (size_t)-2 - offsetof(struct mem_header, body) - HIGH_GUARD_SIZE) {
	result = (struct mem_header *) TclpAlloc(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,
		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
	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",
		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);
    }

    current_malloc_packets++;
    if (current_malloc_packets > maximum_malloc_packets) {
	maximum_malloc_packets = current_malloc_packets;
    }
    current_bytes_malloced += size;







|














|







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 (%" 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 (%" 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;
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
 * Results:
 *	Standard TCL results.
 *
 *----------------------------------------------------------------------
 */
static int
MemoryCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Obj values of arguments. */
{
    const char *fileName;
    FILE *fileP;
    Tcl_DString buffer;







|







794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
 * Results:
 *	Standard TCL results.
 *
 *----------------------------------------------------------------------
 */
static int
MemoryCmd(
    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;
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
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("error accessing %s: %s",
                    TclGetString(objv[2]), Tcl_PosixError(interp)));
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    if (strcmp(TclGetString(objv[1]),"break_on_malloc") == 0) {
	int value;
	if (objc != 3) {
	    goto argError;
	}
	if (Tcl_GetIntFromObj(interp, objv[2], &value) != TCL_OK) {
	    return TCL_ERROR;
	}
	break_on_malloc = (unsigned int) 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",
		"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;
    }







|



|


|




|







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
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("error accessing %s: %s",
                    TclGetString(objv[2]), Tcl_PosixError(interp)));
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    if (strcmp(TclGetString(objv[1]),"break_on_malloc") == 0) {
	Tcl_WideInt value;
	if (objc != 3) {
	    goto argError;
	}
	if (TclGetWideIntFromObj(interp, objv[2], &value) != TCL_OK) {
	    return TCL_ERROR;
	}
	break_on_malloc = value;
	return TCL_OK;
    }
    if (strcmp(TclGetString(objv[1]),"info") == 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%-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;
    }
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
	    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;
	if (objc != 3) {
	    goto argError;
	}
	if (Tcl_GetIntFromObj(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) {







|



|







914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
	    goto bad_suboption;
	}
	alloc_tracing = (strcmp(TclGetString(objv[2]),"on") == 0);
	return TCL_OK;
    }

    if (strcmp(TclGetString(objv[1]),"trace_on_at_malloc") == 0) {
	Tcl_WideInt value;
	if (objc != 3) {
	    goto argError;
	}
	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) {
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
 *	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_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;







<
<
<
<


|







964
965
966
967
968
969
970




971
972
973
974
975
976
977
978
979
980
 *	Returns a standard Tcl completion code.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */




static int
CheckmemCmd(
    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;
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251














































































































































1252
1253
1254
1255
1256
1257
1258
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{
}

int
TclDumpMemoryInfo(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(int) /*flags*/)
{
    return 1;
}

#endif	/* TCL_MEM_DEBUG */















































































































































/*
 *---------------------------------------------------------------------------
 *
 * TclFinalizeMemorySubsystem --
 *
 *	This procedure is called to finalize all the structures that are used







|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{
}

int
TclDumpMemoryInfo(
    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 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
/*
 * 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.

 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"




/*
 * Windows has mktime. The configurators do not check.
 */

#ifdef _WIN32
#define HAVE_MKTIME 1
#endif

/*
 * 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;
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]
 */

typedef struct {
    size_t refCount;		/* Number of live references. */
    Tcl_Obj **literals;		/* Pool of object literals. */
} ClockClientData;

/*
 * Structure containing the fields used in [clock format] and [clock scan]
 */


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 *, int, Tcl_Obj *const[]);
static int		ConvertUTCToLocalUsingC(Tcl_Interp *,
			    TclDateFields *, int);
static int		ConvertLocalToUTC(Tcl_Interp *,
			    TclDateFields *, Tcl_Obj *, int);
static int		ConvertLocalToUTCUsingTable(Tcl_Interp *,
			    TclDateFields *, int, Tcl_Obj *const[]);

static int		ConvertLocalToUTCUsingC(Tcl_Interp *,
			    TclDateFields *, int);
static Tcl_Obj *	LookupLastTransition(Tcl_Interp *, Tcl_WideInt,
			    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(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		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(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		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(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockParseformatargsObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static int		ClockSecondsObjCmd(
			    ClientData clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
static struct tm *	ThreadSafeLocalTime(const time_t *);
static void		TzsetIfNecessary(void);
static void		ClockDeleteCmdProc(ClientData);


/*
 * 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
				 * will always have the ClockClientData sent
				 * to it, but may well ignore this data. */



};

static const struct ClockCommand clockCommands[] = {



    { "getenv",			ClockGetenvObjCmd },


    { "Oldscan",		TclClockOldscanObjCmd },

    { "ConvertLocalToUTC",	ClockConvertlocaltoutcObjCmd },
    { "GetDateFields",		ClockGetdatefieldsObjCmd },
    { "GetJulianDayFromEraYearMonthDay",
		ClockGetjuliandayfromerayearmonthdayObjCmd },
    { "GetJulianDayFromEraYearWeekDay",
		ClockGetjuliandayfromerayearweekdayObjCmd },
    { "ParseFormatArgs",	ClockParseformatargsObjCmd },

    { NULL, NULL }
};

/*
 *----------------------------------------------------------------------
 *
 * TclClockInit --
 *







|
|
|
>






>
>
>









<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
|
<
<
|
<
|
<
<
<
>

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















|
|
<
|


|
|

|
>


|
|



<
<
<
|
|
<
<
|
<
<
|
|
|
>
|
<
<
|
<
<
|
|
|
|
|
|
>
>
|
<
|
|
<
|
|
<
|

|
|
|
>








|


>
>
>



>
>
>
|
>
>
|
>
|
|
|
|
|
|
<
>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29















30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46















47















48



49


50

51



52
53



















54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90



91
92


93


94
95
96
97
98


99


100
101
102
103
104
105
106
107
108

109
110

111
112

113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

150
151
152
153
154
155
156
157
158
/*
 * 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 & 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"
#include "tclStrIdxTree.h"
#include "tclDate.h"

/*
 * Windows has mktime. The configurators do not check.
 */

#ifdef _WIN32
#define HAVE_MKTIME 1
#endif
















/*
 * 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]
 */
















CLOCK_LITERAL_ARRAY(Literals);



















/* Msgcat literals for exact match (mcKey) */


CLOCK_LOCALE_LITERAL_ARRAY(MsgCtLiterals, "");

/* Msgcat index literals prefixed with _IDX_, used for quick dictionary search */



CLOCK_LOCALE_LITERAL_ARRAY(MsgCtLitIdxs, "_IDX_");




















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		ConvertUTCToLocalUsingTable(Tcl_Interp *,
			    TclDateFields *, Tcl_Size, Tcl_Obj *const[],

			    Tcl_WideInt *rangesVal);
static int		ConvertUTCToLocalUsingC(Tcl_Interp *,
			    TclDateFields *, int);
static int		ConvertLocalToUTC(ClockClientData *, Tcl_Interp *,
			    TclDateFields *, Tcl_Obj *timezoneObj, int);
static int		ConvertLocalToUTCUsingTable(Tcl_Interp *,
			    TclDateFields *, int, Tcl_Obj *const[],
			    Tcl_WideInt *rangesVal);
static int		ConvertLocalToUTCUsingC(Tcl_Interp *,
			    TclDateFields *, int);
static int		ClockConfigureObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static void		GetYearWeekDay(TclDateFields *, int);
static void		GetGregorianEraYearDay(TclDateFields *, int);
static void		GetMonthDay(TclDateFields *);



static Tcl_WideInt	WeekdayOnOrBefore(int, Tcl_WideInt);
static Tcl_ObjCmdProc	ClockClicksObjCmd;


static Tcl_ObjCmdProc	ClockConvertlocaltoutcObjCmd;


static int		ClockGetDateFields(ClockClientData *,
			    Tcl_Interp *interp, TclDateFields *fields,
			    Tcl_Obj *timezoneObj, int changeover);
static Tcl_ObjCmdProc	ClockGetdatefieldsObjCmd;
static Tcl_ObjCmdProc	ClockGetjuliandayfromerayearmonthdayObjCmd;


static Tcl_ObjCmdProc	ClockGetjuliandayfromerayearweekdayObjCmd;


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,

			    Tcl_Obj *strObj, ClockFmtScnCmdArgs *opts);
static int		ClockCalcRelTime(DateInfo *info);

static Tcl_ObjCmdProc	ClockAddObjCmd;
static int		ClockValidDate(DateInfo *,

			    ClockFmtScnCmdArgs *, int stage);
static struct tm *	ThreadSafeLocalTime(const time_t *);
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
				 * 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,	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},

    {"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
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. */

    ClockClientData *data;
    int i;



    /* Structure of the 'clock' ensemble */





    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]);












    }

















    /*
     * 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++) {


	strcpy(cmdName + TCL_CLOCK_PREFIX_LEN, clockCmdPtr->name);


	data->refCount++;

	Tcl_CreateObjCommand(interp, cmdName, clockCmdPtr->objCmdProc, data,




























































































































































































































































































		ClockDeleteCmdProc);





    }










































































































































































































































































    /* Make the clock ensemble */































































































































































































































































































    TclMakeEnsemble(interp, "clock", clockImplMap);











































































































































































































































































}

/*
 *----------------------------------------------------------------------
 *
 * ClockConvertlocaltoutcObjCmd --
 *
 *	Tcl command that converts a UTC time to a local time by whatever means
 *	is available.
 *
 * Usage:
 *	::tcl::clock::ConvertUTCToLocal dictionary tzdata changeover
 *
 * Parameters:
 *	dict - Dictionary containing a 'localSeconds' entry.
 *	tzdata - Time zone data
 *	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 */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter vector */
{
    ClockClientData *data = (ClockClientData *)clientData;
    Tcl_Obj *const *lit = data->literals;
    Tcl_Obj *secondsObj;
    Tcl_Obj *dict;
    int changeover;
    TclDateFields fields;
    int created = 0;
    int status;


    /*
     * Check params and convert time.
     */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "dict tzdata changeover");
	return TCL_ERROR;
    }
    dict = objv[1];
    if (Tcl_DictObjGet(interp, dict, lit[LIT_LOCALSECONDS],
	    &secondsObj)!= TCL_OK) {
	return TCL_ERROR;
    }
    if (secondsObj == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("key \"localseconds\" not "
		"found in dictionary", -1));
	return TCL_ERROR;
    }
    if ((TclGetWideIntFromObj(interp, secondsObj,
	    &fields.localSeconds) != TCL_OK)
	|| (TclGetIntFromObj(interp, objv[3], &changeover) != TCL_OK)
	|| ConvertLocalToUTC(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],
	    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
 *
 * Parameters:
 *	seconds - Time expressed in seconds from the Posix epoch.
 *	tzdata - Time zone data of the time zone in which time is to be
 *		 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. */
    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;



    /*
     * Check params.
     */

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "seconds tzdata 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)) {
	Tcl_SetObjResult(interp, lit[LIT_INTEGER_VALUE_TOO_LARGE]);
	return TCL_ERROR;
    }

    /*
     * Convert UTC time to local.
     */


    if (ConvertUTCToLocal(interp, &fields, objv[2], changeover) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Extract Julian day.
     */

    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);







>



>
>
|
>
>
>
>
|
<
<
<
<
<
<
<
<
<
<


















|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>


<





>
>

>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|



|















|




|
<







>





|



|





|


|
<
|
|













|



















|



|
<

















|






|
|

>
>






|












|




|
<
<

>
|



<
<
<
|
<
<
<
<
<
<
<
<
<
<







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191










192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
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) */
    /*
     * Register handler to finalize clock on exit.
     */
    if (!initialized) {
	Tcl_CreateExitHandler(ClockFinalize, NULL);
	initialized = 1;
    }











    /*
     * 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) {
	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 = 0;

    /*
     * Install the commands.

     */

#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++;
	}
	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 "::clock::configure" (internal) 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[] = {
	"-system-tz",	  "-setup-tz",	  "-default-locale",	"-current-locale",
	"-clear",
	"-year-century",  "-century-switch",
	"-min-year", "-max-year", "-max-jdn", "-validate",
	"-init-complete",
	NULL
    };
    enum optionInd {
	CLOCK_SYSTEM_TZ,  CLOCK_SETUP_TZ, CLOCK_DEFAULT_LOCALE, CLOCK_CURRENT_LOCALE,
	CLOCK_CLEAR_CACHE,
	CLOCK_YEAR_CENTURY, CLOCK_CENTURY_SWITCH,
	CLOCK_MIN_YEAR, CLOCK_MAX_YEAR, CLOCK_MAX_JDN, CLOCK_VALIDATE,
	CLOCK_INIT_COMPLETE
    };
    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 timezone changeover
 *
 * Parameters:
 *	dict - Dictionary containing a 'localSeconds' entry.
 *	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(
    void *clientData,		/* Literal table */
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter vector */
{
    ClockClientData *dataPtr = (ClockClientData *)clientData;

    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 timezone changeover");
	return TCL_ERROR;
    }
    dict = objv[1];
    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", TCL_AUTO_LENGTH));
	return TCL_ERROR;
    }
    if ((TclGetWideIntFromObj(interp, secondsObj, &fields.localSeconds) != TCL_OK)

	    || (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, 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 timezone changeover
 *
 * Parameters:
 *	seconds - Time expressed in seconds from the Posix epoch.
 *	timezone - Time zone in which time is to be 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(
    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 *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 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 (TclHasInternalRep(objv[1], &tclBignumType)) {
	Tcl_SetObjResult(interp, lit[LIT_INTEGER_VALUE_TOO_LARGE]);
	return TCL_ERROR;
    }

    /* Extract fields */



    if (ClockGetDateFields(dataPtr, interp, &fields, objv[2],
	    changeover) != TCL_OK) {
	return TCL_ERROR;
    }




    /* Make dict of fields */











    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
	    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;
}

/*
 *----------------------------------------------------------------------
 *
 * ClockGetjuliandayfromerayearmonthdayObjCmd --







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    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
    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));
	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));
	return TCL_ERROR;
    }
    return TclGetIntFromObj(interp, value, storePtr);
}

static int
ClockGetjuliandayfromerayearmonthdayObjCmd(
    ClientData 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;



    /*
     * Check params.
     */

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");







|



















|







|












>
>







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
    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", 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", TCL_AUTO_LENGTH));
	return TCL_ERROR;
    }
    return TclGetIntFromObj(interp, value, storePtr);
}

static int
ClockGetjuliandayfromerayearmonthdayObjCmd(
    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
 *	result being an error message.
 *
 *----------------------------------------------------------------------
 */

static int
ClockGetjuliandayfromerayearweekdayObjCmd(
    ClientData 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;



    /*
     * Check params.
     */

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "dict changeover");







|












>
>







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
 *	result being an error message.
 *
 *----------------------------------------------------------------------
 */

static int
ClockGetjuliandayfromerayearweekdayObjCmd(
    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
 *	in the interpreter result on failure.
 *
 *----------------------------------------------------------------------
 */

static int
ConvertLocalToUTC(

    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Fields of the time */
    Tcl_Obj *tzdata,		/* Time zone data */
    int changeover)		/* Julian Day of the Gregorian transition */
{

    int rowc;			/* Number of rows in tzdata */
    Tcl_Obj **rowv;		/* Pointers to the rows */










    /*



























     * Unpack the tz data.
     */






    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);





    } else {


	return ConvertLocalToUTCUsingTable(interp, fields, rowc, rowv);


    }






































}

/*
 *----------------------------------------------------------------------
 *
 * ConvertLocalToUTCUsingTable --
 *







>


|


>
|

>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>











|
>
>
>
>
>

>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	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 *timezoneObj,	/* Time zone */
    int changeover)		/* Julian Day of the Gregorian transition */
{
    Tcl_Obj *tzdata;		/* Time zone data */
    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) {
	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];

	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): "
		"%d - offs %d => %d <= %d < %d\n",
		(int)fields->localSeconds, fields->tzOffset,
		(int)ltzoc->rangesVal[0], (int)seconds, (int)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
 */

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 *row;
    int cellc;
    Tcl_Obj **cellv;



    int have[8];
    int nHave = 0;
    int 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);

	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;
		break;
	    }
	}
	if (!found) {
	    if (nHave == 8) {
		Tcl_Panic("loop in ConvertLocalToUTCUsingTable");
	    }

	    have[nHave++] = fields->tzOffset;
	}
	fields->seconds = fields->localSeconds - fields->tzOffset;
    }


    fields->tzOffset = have[i];
    fields->seconds = fields->localSeconds - fields->tzOffset;


    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ConvertLocalToUTCUsingC --







|
>


|

>
>
>
|

|
<











<


|
|
>







<
|
|
|
<


<
|
|
|
>
|
<


>
>
|

>
>







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
 */

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_WideInt *rangesVal)	/* Return bounds for time period */
{
    Tcl_Obj *row;
    Tcl_Size cellc;
    Tcl_Obj **cellv;
    struct {
	Tcl_Obj *tzName;
	int tzOffset;
    } have[8];
    int nHave = 0;
    Tcl_Size i;


    /*
     * 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.
     */


    fields->tzOffset = 0;
    fields->seconds = fields->localSeconds;
    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;
	}

	for (i = 0; i < nHave; ++i) {
	    if (have[i].tzOffset == fields->tzOffset) {
		goto found;

	    }
	}

	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].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
    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);
    secondOfDay = (int)(jsec % SECONDS_PER_DAY);
    if (secondOfDay < 0) {
	secondOfDay += SECONDS_PER_DAY;
	fields->julianDay--;
    }
    GetGregorianEraYearDay(fields, changeover);
    GetMonthDay(fields);

    /*
     * Convert the date/time to a 'struct tm'.
     */








<





<
|
<
<
<
|
|







2083
2084
2085
2086
2087
2088
2089

2090
2091
2092
2093
2094

2095



2096
2097
2098
2099
2100
2101
2102
2103
2104
    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;


    /*
     * Convert the given time to a date.
     */


    ClockExtractJDAndSODFromSeconds(fields->julianDay, secondOfDay,



	    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
     * platforms, so seize a mutex before attempting this.
     */

    TzsetIfNecessary();
    Tcl_MutexLock(&clockMutex);
    errno = 0;
    fields->seconds = (Tcl_WideInt) mktime(&timeVal);
    localErrno = errno;
    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));
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|









|







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
     * platforms, so seize a mutex before attempting this.
     */

    TzsetIfNecessary();
    Tcl_MutexLock(&clockMutex);
    errno = 0;
    fields->seconds = (Tcl_WideInt) mktime(&timeVal);
    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", 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
 *
 * Side effects:
 *	Populates the 'tzName' and 'tzOffset' fields.
 *
 *----------------------------------------------------------------------
 */

static int
ConvertUTCToLocal(

    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Fields of the time */
    Tcl_Obj *tzdata,		/* Time zone data */
    int changeover)		/* Julian Day of the Gregorian transition */
{

    int rowc;			/* Number of rows in tzdata */
    Tcl_Obj **rowv;		/* Pointers to the rows */




















    /*




















     * Unpack the tz data.
     */






    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);







    } else {


	return ConvertUTCToLocalUsingTable(interp, fields, rowc, rowv);


    }

























}

/*
 *----------------------------------------------------------------------
 *
 * ConvertUTCToLocalUsingTable --
 *







|

>


|


>
|

>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>











|
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *
 * Side effects:
 *	Populates the 'tzName' and 'tzOffset' fields.
 *
 *----------------------------------------------------------------------
 */

int
ConvertUTCToLocal(
    ClockClientData *dataPtr,	/* Literal pool, etc. */
    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Fields of the time */
    Tcl_Obj *timezoneObj,	/* Time zone */
    int changeover)		/* Julian Day of the Gregorian transition */
{
    Tcl_Obj *tzdata;		/* Time zone data */
    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) {
	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];

	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
 *----------------------------------------------------------------------
 */

static int
ConvertUTCToLocalUsingTable(
    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Fields of the date */
    int rowc,			/* Number of rows in the conversion table
				 * (>= 1) */
    Tcl_Obj *const rowv[])	/* Rows of the conversion table */

{
    Tcl_Obj *row;		/* Row containing the current information */
    int 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) {
	return TCL_ERROR;
    }

    /*
     * Convert the time.
     */

    fields->tzName = cellv[3];
    Tcl_IncrRefCount(fields->tzName);
    fields->localSeconds = fields->seconds + fields->tzOffset;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|

|
>


|






|
|
|
|







|
<







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
 *----------------------------------------------------------------------
 */

static int
ConvertUTCToLocalUsingTable(
    Tcl_Interp *interp,		/* Tcl interpreter */
    TclDateFields *fields,	/* Fields of the date */
    Tcl_Size rowc,		/* Number of rows in the conversion table
				 * (>= 1) */
    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 */
    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, 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.
     */

    TclSetObjRef(fields->tzName, cellv[3]);

    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
    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 */

    /*
     * 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);
	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);
	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
	    + 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);
    diff %= 3600;
    sprintf(buffer+3, "%02d", diff / 60);
    diff %= 60;
    if (diff > 0) {
	sprintf(buffer+5, "%02d", diff);
    }
    fields->tzName = Tcl_NewStringObj(buffer, -1);
    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 *
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 */

{
    int l;
    int u;
    Tcl_Obj *compObj;
    Tcl_WideInt compVal;

    /*
     * 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) {




	return rowv[0];
    }

    /*
     * Binary-search to find the transition.
     */

    l = 0;
    u = rowc-1;
    while (l < u) {
	int 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;

	} else {
	    u = m-1;

	}
    }





    return rowv[l];
}

/*
 *----------------------------------------------------------------------
 *
 * GetYearWeekDay --







|








|
|







|
|

















|















|

|

|
|

|
<

















|



|
|
>

<
|

|















|
>
>
>
>








|

|







>

|
>


>
>
>
>
>







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
    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], *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", 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)", 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 * 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 = '+';
    }
    TclItoAw(buffer + 1, diff / 3600, '0', 2);
    diff %= 3600;
    p = TclItoAw(buffer + 3, diff / 60, '0', 2);
    diff %= 60;
    if (diff != 0) {
	p = TclItoAw(buffer + 5, diff, '0', 2);
    }
    TclSetObjRef(fields->tzName, Tcl_NewStringObj(buffer, p - buffer));

    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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
LookupLastTransition(
    Tcl_Interp *interp,		/* Interpreter for error messages */
    Tcl_WideInt tick,		/* Time from the epoch */
    Tcl_Size rowc,		/* Number of rows of tzdata */
    Tcl_Obj *const *rowv,	/* Rows in tzdata */
    Tcl_WideInt *rangesVal)	/* Return bounds for time period */
{

    Tcl_Size l, u;
    Tcl_Obj *compObj;
    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 < (fromVal = compVal)) {
	if (rangesVal) {
	    rangesVal[0] = fromVal;
	    rangesVal[1] = toVal;
	}
	return rowv[0];
    }

    /*
     * Binary-search to find the transition.
     */

    l = 0;
    u = rowc - 1;
    while (l < u) {
	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;
	    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
GetYearWeekDay(
    TclDateFields *fields,	/* Date to convert, must have 'julianDay' */
    int changeover)		/* Julian Day Number of the Gregorian
				 * transition */
{
    TclDateFields temp;
    int dayOfFiscalYear;



    /*
     * 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;







>
>







2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
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
 */

static void
GetGregorianEraYearDay(
    TclDateFields *fields,	/* Date fields containing 'julianDay' */
    int changeover)		/* Gregorian transition date */
{
    int jday = fields->julianDay;
    int day;
    int year;
    int n;

    if (jday >= changeover) {
	/*
	 * Gregorian calendar.
	 */

	fields->gregorian = 1;







|
|
|
|







2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
 */

static void
GetGregorianEraYearDay(
    TclDateFields *fields,	/* Date fields containing 'julianDay' */
    int changeover)		/* Gregorian transition date */
{
    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

static void
GetMonthDay(
    TclDateFields *fields)	/* Date to convert */
{
    int day = fields->dayOfYear;
    int month;
    const int *h = hath[IsGregorianLeapYear(fields)];













    for (month = 0; month < 12 && day > h[month]; ++month) {


	day -= h[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
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
				 * given year */
    TclDateFields firstWeek;



    /*
     * Find January 4 in the ISO8601 year, which will always be in week 1.
     */

    firstWeek.isBce = fields->isBce;
    firstWeek.year = fields->iso8601Year;







|

>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
|
>
>
|




















|





|


>
>







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

static void
GetMonthDay(
    TclDateFields *fields)	/* Date to convert */
{
    int day = fields->dayOfYear;
    int month;
    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 {
	    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.
 *
 *----------------------------------------------------------------------
 */

void
GetJulianDayFromEraYearWeekDay(
    TclDateFields *fields,	/* Date to convert */
    int changeover)		/* Julian Day Number of the Gregorian
				 * transition */
{
    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
 *
 * Side effects:
 *	Stores day number in 'julianDay'
 *
 *----------------------------------------------------------------------
 */

static void
GetJulianDayFromEraYearMonthDay(
    TclDateFields *fields,	/* Date to convert */
    int changeover)		/* Gregorian transition date as a Julian Day */
{

    int year, ym1, month, mm1, q, r, ym1o4, ym1o100, ym1o400;

    if (fields->isBce) {
	year = 1 - fields->year;
    } else {
	year = fields->year;
    }








|




>
|







2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
 *
 * Side effects:
 *	Stores day number in 'julianDay'
 *
 *----------------------------------------------------------------------
 */

void
GetJulianDayFromEraYearMonthDay(
    TclDateFields *fields,	/* Date to convert */
    int changeover)		/* Gregorian transition date as a Julian Day */
{
    Tcl_WideInt year, ym1, 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
    /*
     * Adjust the year after reducing the month.
     */

    fields->gregorian = 1;
    if (year < 1) {
	fields->isBce = 1;
	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)
	ym1o4 = ym1 / 4;
    else {
	ym1o4 = - (int) (((unsigned int) -ym1) / 4);
    }
#endif
    if (ym1 % 4 < 0) {
	ym1o4--;
    }
    ym1o100 = ym1 / 100;







|
















|

|







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
    /*
     * Adjust the year after reducing the month.
     */

    fields->gregorian = 1;
    if (year < 1) {
	fields->isBce = 1;
	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) {
	ym1o4 = ym1 / 4;
    } 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
		+ ym1o4;
    }
}

/*
 *----------------------------------------------------------------------
 *























































 * 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
IsGregorianLeapYear(
    TclDateFields *fields)	/* Date to test */
{
    int year = fields->year;

    if (fields->isBce) {
	year = 1 - year;
    }
    if (year%4 != 0) {
	return 0;
    } else if (!(fields->gregorian)) {
	return 1;
    } else if (year%400 == 0) {
	return 1;
    } 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
WeekdayOnOrBefore(
    int dayOfWeek,		/* Day of week; Sunday == 0 or 7 */
    int julianDay)		/* Reference date */
{
    int k = (dayOfWeek + 6) % 7;
    if (k < 0) {
	k += 7;
    }
    return julianDay - ((julianDay - k) % 7);
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|



|




|



|

|




















|


|







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
		+ 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.
 *
 *----------------------------------------------------------------------
 */

int
IsGregorianLeapYear(
    TclDateFields *fields)	/* Date to test */
{
    Tcl_WideInt year = fields->year;

    if (fields->isBce) {
	year = 1 - year;
    }
    if (year % 4 != 0) {
	return 0;
    } else if (!(fields->gregorian)) {
	return 1;
    } else if (year % 400 == 0) {
	return 1;
    } 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 Tcl_WideInt
WeekdayOnOrBefore(
    int dayOfWeek,		/* Day of week; Sunday == 0 or 7 */
    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
 *	the value of the variable if the variable does exist,
 *
 *----------------------------------------------------------------------
 */

int
ClockGetenvObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{





    const char *varName;
    const char *varValue;


    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    }












    varName = TclGetString(objv[1]);
    varValue = getenv(varName);
    if (varValue == NULL) {

	varValue = "";
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(varValue, -1));

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * ThreadSafeLocalTime --







|




>
>
>
>
>


>





>
>
>
>
>
>
>
>
>
>
>
>


|
>
|

<
>







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
 *	the value of the variable if the variable does exist,
 *
 *----------------------------------------------------------------------
 */

int
ClockGetenvObjCmd(
    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) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		varValue, TCL_AUTO_LENGTH));
    }

#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
{
    /*
     * 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);
#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));
    Tcl_MutexUnlock(&clockMutex);
#endif
    return tmPtr;
}

/*----------------------------------------------------------------------
 *







|









|







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
{
    /*
     * 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
    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, 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
 * documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockClicksObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter values */
{
    static const char *const clicksSwitches[] = {
	"-milliseconds", "-microseconds", NULL
    };







|







3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
 * documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockClicksObjCmd(
    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
    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?");
	return TCL_ERROR;
    }

    switch (index) {
    case CLICKS_MILLIS:
	Tcl_GetTime(&now);
	clicks = (Tcl_WideInt) now.sec * 1000 + now.usec / 1000;
	break;
    case CLICKS_NATIVE:
#ifdef TCL_WIDE_CLICKS
	clicks = TclpGetWideClicks();
#else
	clicks = (Tcl_WideInt) TclpGetClicks();
#endif
	break;
    case CLICKS_MICROS:
	clicks = TclpGetMicroseconds();
	break;
    }








|






|





|







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
    case 2:
	if (Tcl_GetIndexFromObj(interp, objv[1], clicksSwitches, "option", 0,
		&index) != TCL_OK) {
	    return TCL_ERROR;
	}
	break;
    default:
	Tcl_WrongNumArgs(interp, 0, objv, "clock clicks ?-switch?");
	return TCL_ERROR;
    }

    switch (index) {
    case CLICKS_MILLIS:
	Tcl_GetTime(&now);
	clicks = now.sec * 1000LL + now.usec / 1000;
	break;
    case CLICKS_NATIVE:
#ifdef TCL_WIDE_CLICKS
	clicks = TclpGetWideClicks();
#else
	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
 * user documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockMillisecondsObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter values */
{
    Tcl_Time now;


    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    Tcl_GetTime(&now);
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt)
	    now.sec * 1000 + now.usec / 1000));

    return TCL_OK;
}

/*----------------------------------------------------------------------
 *
 * ClockMicrosecondsObjCmd -
 *







|





>


|



|
|
>







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
 * user documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockMillisecondsObjCmd(
    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, 0, objv, "clock milliseconds");
	return TCL_ERROR;
    }
    Tcl_GetTime(&now);
    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
 * user documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockMicrosecondsObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter values */
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(TclpGetMicroseconds()));
    return TCL_OK;
}












/*
 *-----------------------------------------------------------------------------
 *
 * ClockParseformatargsObjCmd --
 *
 *	Parses the arguments for [clock format].
 *




 * Results:
 *	Returns a standard Tcl result, whose value is a four-element list
 *	comprising the time format, the locale, and the timezone.
 *
 * 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.
 *
 *-----------------------------------------------------------------------------
 */







static int
ClockParseformatargsObjCmd(
    ClientData 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;
    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 };
    enum optionInd {
	CLOCK_FORMAT_FORMAT,	CLOCK_FORMAT_GMT,	CLOCK_FORMAT_LOCALE,
	CLOCK_FORMAT_TIMEZONE
    };
    int optionIndex;		/* Index of an option. */
    int saw = 0;		/* Flag == 1 if option was seen already. */

    Tcl_WideInt clockVal;	/* Clock value - just used to parse. */
    int i;


    /*
     * Args consist of a time followed by keyword-value pairs.
     */


    if (objc < 2 || (objc % 2) != 0) {
	Tcl_WrongNumArgs(interp, 0, objv,
		"clock format clockval ?-format string? "
		"?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?");
	Tcl_SetErrorCode(interp, "CLOCK", "wrongNumArgs", NULL);
	return TCL_ERROR;
    }

    /*
     * 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) {









	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		&optionIndex) != TCL_OK) {
	    Tcl_SetErrorCode(interp, "CLOCK", "badOption",








		    TclGetString(objv[i]), NULL);
	    return TCL_ERROR;

	}
	switch (optionIndex) {
	case CLOCK_FORMAT_FORMAT:



	    formatObj = objv[i+1];
	    break;
	case CLOCK_FORMAT_GMT:
	    if (Tcl_GetBooleanFromObj(interp, objv[i+1], &gmtFlag) != TCL_OK){
		return TCL_ERROR;
	    }
	    break;
	case CLOCK_FORMAT_LOCALE:
	    localeObj = objv[i+1];
	    break;
	case CLOCK_FORMAT_TIMEZONE:
	    timezoneObj = objv[i+1];



















	    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);
	return TCL_ERROR;
    }
    if (gmtFlag) {






	timezoneObj = litPtr[LIT_GMT];


























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































    }

    /*
     * Return options as a list.
     */

    Tcl_SetObjResult(interp, Tcl_NewListObj(3, results));
    return TCL_OK;



#undef timezoneObj

#undef localeObj

#undef formatObj







}

/*----------------------------------------------------------------------
 *
 * ClockSecondsObjCmd -
 *
 *	Returns a count of microseconds since the epoch.







|





|






>
>
>
>
>
>
>
>
>
>
>



|

|

>
>
>
>

|
|

<
<
<
<


>
>
>
>
>
>


|
<
|
>
>
|
|
>
>

>
|
<
<
<
<
<

|
|
|

|
|



>
|
<

>
|
<
<
|
>
|
|
<
<
<
|






<
<
<

>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
>
>
|
<
>


|
>
>
>
|

|
|



|
|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









<
<
<
|
|
|
>
|



>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|


|
|
>
|
>
|
>
|
>
|
>
>
>
>
>
>
>







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
 * user documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockMicrosecondsObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter values */
{
    if (objc != 1) {
	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;
}

/*
 *-----------------------------------------------------------------------------
 *
 * ClockParseFmtScnArgs --
 *
 *	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, and stores parsed options
 *	(format, the locale, timezone and base) in structure "opts".
 *




 *-----------------------------------------------------------------------------
 */

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
ClockParseFmtScnArgs(

    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 = opts->dataPtr;





    int gmtFlag = 0;
    static const char *const options[] = {
	"-base", "-format", "-gmt", "-locale", "-timezone", "-validate", NULL
    };
    enum optionInd {
	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 baseVal;	/* Base time, expressed in seconds from the Epoch */


    if (operation == CLC_OP_SCN) {
    	/* default flags (from configure) */


    	opts->flags |= dataPtr->defFlags & CLF_VALIDATE;
    } else {
    	/* clock value (as current base) */
	opts->baseObj = objv[(baseIdx = 1)];



	saw |= 1 << CLC_ARGS_BASE;
    }

    /*
     * Extract values for the keywords.
     */




    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) {
	    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])));

	    goto badOption;
	}
	switch (optionIndex) {
	case CLC_ARGS_FORMAT:
	    if (operation == CLC_OP_ADD) {
		goto badOptionMsg;
	    }
	    opts->formatObj = objv[i + 1];
	    break;
	case CLC_ARGS_GMT:
	    if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &gmtFlag) != TCL_OK){
		return TCL_ERROR;
	    }
	    break;
	case CLC_ARGS_LOCALE:
	    opts->localeObj = objv[i + 1];
	    break;
	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 ((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);
	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 option "-now" */
	if ((baseObj->bytes && baseObj->length == 4 && baseObj->bytes[1] == 'n')
		|| TclGetWideIntFromObj(NULL, baseObj, &baseVal) != TCL_OK) {
	    /* we accept "-now" as current date-time */
	    static const char *const nowOpts[] = {
		"-now", NULL
	    };
	    int idx;

	    if (Tcl_GetIndexFromObj(interp, baseObj, nowOpts, "seconds",
		    TCL_EXACT, &idx) == TCL_OK) {
		goto baseNow;
	    }

	    if (TclHasInternalRep(baseObj, &tclBignumType)) {
		goto baseOverflow;
	    }

	    Tcl_AppendResult(interp, " or integer", NULL);
	    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;
	}
    }

    /* Local seconds to UTC (stored in yydate.seconds) */

    if (info->flags & CLF_ASSEMBLE_SECONDS) {
	yydate.localSeconds =
		-210866803200LL
		+ (SECONDS_PER_DAY * yydate.julianDay)
		+ (yySecondOfDay % SECONDS_PER_DAY);
    }

    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 %d, "
	    "yySecondOfDay %d, sec %d, daySec %d, tzOffset %d\n",
	    yyMonth, yyDay, yydate.dayOfYear, yyHour, yyMinutes, yySeconds,
	    yySecondOfDay, (int)yydate.localSeconds, (int)(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;
	} else if ((info->flags & CLF_MONTH)) {
	    const int *h = hath[IsGregorianLeapYear(&yydate)];

	    if (yyDay > h[yyMonth - 1]) {
		errMsg = "invalid 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) ? 23 : 12)) {
	    errMsg = "invalid time (hour)";
	    errCode = "hour";
	    goto error;
	}
	/* minutes */
	if (yyMinutes < 0 || yyMinutes > 59) {
	    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) {
	    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;
	}
    }

    /*
     * Do relative times (if not yet already processed interim):
     */

    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
 * documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockSecondsObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const *objv)	/* Parameter values */
{
    Tcl_Time now;


    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;
    }
    Tcl_GetTime(&now);


    Tcl_SetObjResult(interp, Tcl_NewWideIntObj((Tcl_WideInt) now.sec));
    return TCL_OK;
}







































































/*
 *----------------------------------------------------------------------
 *
 * TzsetIfNecessary --
 *
 *	Calls the tzset() library function if the contents of the TZ
 *	environment variable has changed.
 *
 * Results:

 *	None.
 *
 * Side effects:
 *	Calls tzset.
 *
 *----------------------------------------------------------------------
 */



























static void
TzsetIfNecessary(void)
{



    static char* tzWas = (char *)INT2PTR(-1);	/* Previous value of TZ, protected by





				 * clockMutex. */




    const char *tzIsNow;	/* Current value of TZ */




    Tcl_MutexLock(&clockMutex);


    tzIsNow = getenv("TZ");

    if (tzIsNow != NULL && (tzWas == NULL || tzWas == INT2PTR(-1)
	    || strcmp(tzIsNow, tzWas) != 0)) {
	tzset();
	if (tzWas != NULL && tzWas != INT2PTR(-1)) {
	    Tcl_Free(tzWas);
	}
	tzWas = (char *)Tcl_Alloc(strlen(tzIsNow) + 1);
	strcpy(tzWas, tzIsNow);

    } else if (tzIsNow == NULL && tzWas != NULL) {
	tzset();

	if (tzWas != INT2PTR(-1)) Tcl_Free(tzWas);

	tzWas = NULL;



    }
    Tcl_MutexUnlock(&clockMutex);
}


/*
 *----------------------------------------------------------------------
 *
 * ClockDeleteCmdProc --
 *
 *	Remove a reference to the clock client data, and clean up memory
 *	when it's all gone.
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ClockDeleteCmdProc(
    ClientData 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]);
	}
	Tcl_Free(data->literals);
	Tcl_Free(data);
    }

}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|





>


|



>
>
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










>
|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>

>

>
>
|
>
|
|

|
|

|
|
>
|

>
|
>
|
>
>
>


|
>
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<

|
<
>

<
|

|
<
|
|
<
<
|
>









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
 * documentation for details on what it does.
 *
 *----------------------------------------------------------------------
 */

int
ClockSecondsObjCmd(
    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, 0, objv, "clock seconds");
	return TCL_ERROR;
    }
    Tcl_GetTime(&now);
    TclNewUIntObj(timeObj, (Tcl_WideUInt)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
 *	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 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. */

    /*
     * 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) {
	tzNow = getenv("TZ");
    }
    if (tzNow != NULL && (tz.was == NULL || tz.was == TZ_INIT_MARKER
	    || wcscmp(tzNow, tz.was) != 0)) {
	tzset();
	if (tz.was != NULL && tz.was != TZ_INIT_MARKER) {
	    Tcl_Free(tz.was);
	}
	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) {
	    Tcl_Free(tz.was);
	}
	tz.was = NULL;
	epoch = ++tz.epoch;
    } else {
	epoch = tz.epoch;
    }
    Tcl_MutexUnlock(&clockMutex);

    return epoch;
}














static void
ClockFinalize(

    TCL_UNUSED(void *))
{

    ClockFrmScnFinalize();

    if (tz.was && tz.was != TZ_INIT_MARKER) {

	Tcl_Free(tz.was);
    }



    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
/*
 * 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);

TCL_DECLARE_MUTEX(ClockFmtMutex);	/* Serializes access to common format list. */

static void		ClockFmtScnStorageDelete(ClockFmtScnStorage *fss);

#ifndef TCL_CLOCK_FULL_COMPAT
#define TCL_CLOCK_FULL_COMPAT 1
#endif

/*
 * Derivation of tclStringHashKeyType with another allocEntryProc
 */

static Tcl_HashKeyType ClockFmtScnStorageHashKeyType;

#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__)
# 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__)
# 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);
	/* fulling 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-- = '-';
    }
    /* fulling 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);
	/* fulling 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-- = '-';
    }
    /* fulling 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 type */
	memcpy(&ClockFmtScnStorageHashKeyType, &tclStringHashKeyType, sizeof(tclStringHashKeyType));
	ClockFmtScnStorageHashKeyType.allocEntryProc = ClockFmtScnStorageAllocProc;
	ClockFmtScnStorageHashKeyType.freeEntryProc = ClockFmtScnStorageFreeProc;

	/* 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 : "", "\"", 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_AttemptRealloc((char *)(chain),		\
	    (tokCnt + CLOCK_MIN_TOK_CHAIN_BLOCK_SIZE) * sizeof(*(tok))); \
	if ((chain) == NULL) { 						\
	    goto done;							\
	}								\
	(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 (*p == ' ' || 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:
	    {
		ClockScanToken *wordTok = tok;

		if (tok > scnTok && (tok - 1)->map == &ScnWordTokenMap) {
		    wordTok = tok - 1;
		}
		/* new word token */
		if (wordTok == tok) {
		    wordTok->tokWord.start = p;
		    wordTok->map = &ScnWordTokenMap;
		    AllocTokenInChain(tok, scnTok, fss->scnTokC, ClockScanToken *);
		    tokCnt++;
		}
		if (isspace(UCHAR(*p))) {
		    fss->scnSpaceCount++;
		}
		p = Tcl_UtfNext(p);
		wordTok->tokWord.end = p;
		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;
    }
  done:
    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: {
		ClockFormatToken *wordTok = tok;

		if (tok > fmtTok && (tok - 1)->map == &FmtWordTokenMap) {
		    wordTok = tok - 1;
		}
		if (wordTok == tok) {
		    wordTok->tokWord.start = p;
		    wordTok->map = &FmtWordTokenMap;
		    AllocTokenInChain(tok, fmtTok, fss->fmtTokC, ClockFormatToken *);
		    tokCnt++;
		}
		p = Tcl_UtfNext(p);
		wordTok->tokWord.end = p;
		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;
    }
  done:
    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()
{
    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
/*
 * 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.
 *
 * 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 _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_Obj ***varvList;	/* Array of var name lists. */
    Tcl_Obj **vCopyList;	/* Copies of var name list arguments. */
    int *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	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,
			    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;






|
|






>
>












|
|
|
|
|


|

















>










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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 © 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. */
    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. */
    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,
			    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_BreakObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_BreakObjCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_CatchObjCmd(
    ClientData 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_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;







|









|







149
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(
    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(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
     */

    return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
}

static int
CatchObjCmdCallback(
    ClientData 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];







|







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(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_CdObjCmd(
    TCL_UNUSED(ClientData),
    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 {

	TclNewLiteralStringObj(dir, "~");


	Tcl_IncrRefCount(dir);
    }
    if (Tcl_FSConvertToPathType(interp, dir) != TCL_OK) {
	result = TCL_ERROR;
    } else {




	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;
	}
    }







|















>
|
>
>





>
>
>
>
|
>







254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
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(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);
	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);
	}
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ConcatObjCmd(
    TCL_UNUSED(ClientData),
    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));
    }







|







317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ConcatObjCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ContinueObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ContinueObjCmd(
    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
 */

Tcl_Command
TclInitEncodingCmd(
    Tcl_Interp* interp)		/* Tcl interpreter */
{
    static const EnsembleImplMap encodingImplMap[] = {
	{"convertfrom", EncodingConvertfromObjCmd, TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
	{"convertto",   EncodingConverttoObjCmd,   TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
	{"dirs",        EncodingDirsObjCmd,        TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
	{"names",       EncodingNamesObjCmd,       TclCompileBasic0ArgCmd,    NULL, NULL, 0},

	{"system",      EncodingSystemObjCmd,      TclCompileBasic0Or1ArgCmd, NULL, NULL, 1},
	{NULL,          NULL,                      NULL,                      NULL, NULL, 0}
    };

    return TclMakeEnsemble(interp, "encoding", encodingImplMap);
}






































































































/*
 *----------------------------------------------------------------------
 *
 * 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_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 */
    const char *bytesPtr;	/* Pointer to the first byte of the array */









    if (objc == 2) {



	encoding = Tcl_GetEncoding(interp, NULL);
	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");
	return TCL_ERROR;












    }

    /*

     * Convert the string into a byte array in 'ds'
     */
    bytesPtr = (char *) TclGetByteArrayFromObj(data, &length);





    Tcl_ExternalToUtfDString(encoding, bytesPtr, length, &ds);



    /*
     * Note that we cannot use Tcl_DStringResult here because it will
     * truncate the string at the first null byte.
     */

    Tcl_SetObjResult(interp, TclDStringToObj(&ds));

    /*
     * We're done with the encoding
     */

    Tcl_FreeEncoding(encoding);
    return TCL_OK;

}

/*







|
|


>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
















|







|

>
>
>
>

>
>
>
>
|
>
>
>
|
|
|
<
|
|
>
>
>
>
>
|
>
|
>
|

>
>
>
>
>
>
>
>
>
>
>
>



>
|

<
>
>
>
>
>
|
>
|
>





|

<
|
<







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
 */

Tcl_Command
TclInitEncodingCmd(
    Tcl_Interp* interp)		/* Tcl interpreter */
{
    static const EnsembleImplMap encodingImplMap[] = {
	{"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(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 */
    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;
    }

    /*
     * Convert the string into a byte array in 'ds'.
     */
    bytesPtr = (char *) Tcl_GetBytesFromObj(interp, data, &length);

    if (bytesPtr == NULL) {

	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
     * 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;
	}
    }
    /*
     * Note that we cannot use Tcl_DStringResult here because it will
     * truncate the string at the first null byte.
     */

    Tcl_SetObjResult(interp, Tcl_DStringToObj(&ds));


    /* 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
 *	A standard Tcl result.
 *
 *----------------------------------------------------------------------
 */

int
EncodingConverttoObjCmd(
    TCL_UNUSED(ClientData),
    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 */
    const char *stringPtr;	/* Pointer to the first byte of the string */

    /* TODO - ADJUST OBJ INDICES WHEN ENSEMBLIFYING THIS */

    if (objc == 2) {
	encoding = Tcl_GetEncoding(interp, NULL);
	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");

	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)));
    Tcl_DStringFree(&ds);

    /*
     * We're done with the encoding
     */

    Tcl_FreeEncoding(encoding);
    return TCL_OK;

}

/*







|







|

|
<
|
|
|
<
<
<
<
|
<
<
|
>








|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|


<
|
<







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
 *	A standard Tcl result.
 *
 *----------------------------------------------------------------------
 */

int
EncodingConverttoObjCmd(
    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 */
    Tcl_Size length;		/* Length of the string being converted */
    const char *stringPtr;	/* Pointer to the first byte of the string */
    int result;

    int flags;
    Tcl_Obj *failVarObj;
    Tcl_Size errorLocation;







    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);
    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 */


    Tcl_FreeEncoding(encoding);
    return TCL_OK;

}

/*
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
 *	Can set the encoding search path.
 *
 *----------------------------------------------------------------------
 */

int
EncodingDirsObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *dirListObj;

    if (objc > 2) {







|







704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
 *	Can set the encoding search path.
 *
 *----------------------------------------------------------------------
 */

int
EncodingDirsObjCmd(
    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

    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);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, dirListObj);
    return TCL_OK;
}

/*







|







726
727
728
729
730
731
732
733
734
735
736
737
738
739
740

    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",
		(void *)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
 *	Returns a standard Tcl result
 *
 *-----------------------------------------------------------------------------
 */

int
EncodingNamesObjCmd(
    TCL_UNUSED(ClientData),
    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;
}





























/*
 *-----------------------------------------------------------------------------
 *
 * 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_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));
    } else {
	return Tcl_SetSystemEncoding(interp, TclGetString(objv[1]));
    }
    return TCL_OK;
}

/*







|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



















|










|







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
 *	Returns a standard Tcl result
 *
 *-----------------------------------------------------------------------------
 */

int
EncodingNamesObjCmd(
    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(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));
    } 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ErrorObjCmd(
    TCL_UNUSED(ClientData),
    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)) {







|







844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ErrorObjCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
EvalCmdErrMsg(
    TCL_UNUSED(ClientData *),
    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,
    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_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;







|












|









|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
EvalCmdErrMsg(
    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(
    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(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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExitObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_WideInt value;

    if ((objc != 1) && (objc != 2)) {







|







975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExitObjCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExprObjCmd(
    ClientData 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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *resultPtr, *objPtr;

    if (objc < 2) {







|









|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExprObjCmd(
    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(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
    }

    return Tcl_NRExprObj(interp, objPtr, resultPtr);
}

static int
ExprCallback(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultPtr = (Tcl_Obj *)data[0];
    Tcl_Obj *objPtr = (Tcl_Obj *)data[1];

    if (objPtr != NULL) {







|







1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
    }

    return Tcl_NRExprObj(interp, objPtr, resultPtr);
}

static int
ExprCallback(
    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
	{"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},

	{"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},







>







1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
	{"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
	{"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},

	{"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);
}







>







1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
	{"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
 *	May update the access time on the file, if requested by the user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrAccessTimeCmd(
    TCL_UNUSED(ClientData),
    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;
    }
#endif

    if (objc == 3) {
	/*
	 * Need separate variable for reading longs from an object on 64-bit
	 * platforms. [Bug 698146]







|

















|
|
|
|







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
 *	May update the access time on the file, if requested by the user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrAccessTimeCmd(
    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;
    }
#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
 *	user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrModifyTimeCmd(
    TCL_UNUSED(ClientData),
    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;
    }
#endif
    if (objc == 3) {
	/*
	 * Need separate variable for reading longs from an object on 64-bit
	 * platforms. [Bug 698146]
	 */







|

















|
|
|
|







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
 *	user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrModifyTimeCmd(
    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;
    }
#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
 *	Writes to an array named by the user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrLinkStatCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    if (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;
    }



    return StoreStatData(interp, objv[2], &buf);

}

/*
 *----------------------------------------------------------------------
 *
 * FileAttrStatCmd --
 *







|






|
|





>
>
>
|
>







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
 *	Writes to an array named by the user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrLinkStatCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    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);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	Writes to an array named by the user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrStatCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    if (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;
    }



    return StoreStatData(interp, objv[2], &buf);

}

/*
 *----------------------------------------------------------------------
 *
 * FileAttrTypeCmd --
 *







|






|
|





>
>
>
|
>







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
 *	Writes to an array named by the user.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrStatCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    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);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * FileAttrTypeCmd --
 *
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrTypeCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    if (objc != 2) {







|







1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrTypeCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrSizeCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    if (objc != 2) {







|







1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrSizeCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;

    if (objc != 2) {
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsDirectoryCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;
    int value = 0;








|







1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsDirectoryCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsExecutableCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;







|







1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsExecutableCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsExistingCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;







|







1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsExistingCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsFileCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_StatBuf buf;
    int value = 0;








|







1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsFileCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsOwnedCmd(
    TCL_UNUSED(ClientData),
    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;
    }















#if defined(_WIN32)
    value = TclWinFileOwned(objv[1]);
#else
    if (GetStatBuf(NULL, objv[1], Tcl_FSStat, &buf) == TCL_OK) {
	value = (geteuid() == buf.st_uid);
    }
#endif







|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsOwnedCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsReadableCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;







|







1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsReadableCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsWritableCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;







|







1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileAttrIsWritableCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathDirNameCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *dirPtr;

    if (objc != 2) {







|







1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathDirNameCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathExtensionCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *dirPtr;

    if (objc != 2) {







|







1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathExtensionCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathRootNameCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *dirPtr;

    if (objc != 2) {







|







1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathRootNameCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathTailCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *dirPtr;

    if (objc != 2) {







|







1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathTailCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathFilesystemCmd(
    TCL_UNUSED(ClientData),
    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);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, fsInfo);
    return TCL_OK;
}

/*







|














|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathFilesystemCmd(
    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]), (void *)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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathJoinCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?");
	return TCL_ERROR;







|







1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathJoinCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathNativeNameCmd(
    TCL_UNUSED(ClientData),
    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));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * PathNormalizeCmd --







|













|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathNativeNameCmd(
    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, Tcl_DStringToObj(&ds));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * PathNormalizeCmd --
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathNormalizeCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *fileName;

    if (objc != 2) {







|







2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathNormalizeCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathSplitCmd(
    TCL_UNUSED(ClientData),
    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);
    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);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, res);
    return TCL_OK;
}

/*







|










|





|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathSplitCmd(
    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], (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",
		(void *)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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathTypeCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *typeName;

    if (objc != 2) {







|







2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PathTypeCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FilesystemSeparatorCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc < 1 || objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?name?");
	return TCL_ERROR;







|







2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FilesystemSeparatorCmd(
    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
    } 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);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, separatorObj);
    }
    return TCL_OK;
}








|







2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
    } 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]), (void *)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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FilesystemVolumesCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, NULL);
	return TCL_ERROR;







|







2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FilesystemVolumesCmd(
    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
    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;


    if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
	value = 0;




    } else {

	value = (Tcl_FSAccess(pathPtr, mode) == 0);
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(value));

    return TCL_OK;
}








>



>
>
>
>

>







2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
    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
    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;


    if (Tcl_FSConvertToPathType(interp, pathPtr) != TCL_OK) {
	return TCL_ERROR;
    }





    status = statProc(pathPtr, statPtr);



    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.
 *
 * 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;
    unsigned short mode;

    /*

     * Assume Tcl_ObjSetVar2() does not keep a copy of the field name!




























     *

     * 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);				\







>





>
>
>
>
|
>
>



















|



















|


<
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>







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
    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);
    }
    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 (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, *result;
    unsigned short mode;


    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

    /*
     * 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("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));
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    STORE_ARY("blocks",	Tcl_NewWideIntObj((Tcl_WideInt)statPtr->st_blocks));
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
    STORE_ARY("blksize", Tcl_NewWideIntObj((long)statPtr->st_blksize));
#endif





    STORE_ARY("atime",	Tcl_NewWideIntObj(Tcl_GetAccessTimeFromStat(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;







|



|

|




>
>
>
>
>

|
>







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

    /*
     * 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(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(statPtr->st_size));
#ifdef HAVE_STRUCT_STAT_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("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
 *					|____________________|
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ForObjCmd(
    ClientData 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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    ForIterData *iterPtr;








|









|







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
 *					|____________________|
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ForObjCmd(
    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(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
     */

    return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
}

static int
ForSetupCallback(
    ClientData 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[],
    Tcl_Interp *interp,
    int result)
{
    ForIterData *iterPtr = (ForIterData *)data[0];
    Tcl_Obj *boolObj;

    switch (result) {







|


















|







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
     */

    return TclNREvalObjEx(interp, objv[1], 0, iPtr->cmdFramePtr, 1);
}

static int
ForSetupCallback(
    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(
    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
    }
    TclSmallFreeEx(interp, iterPtr);
    return result;
}

static int
ForCondCallback(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    ForIterData *iterPtr = (ForIterData *)data[0];
    Tcl_Obj *boolObj = (Tcl_Obj *)data[1];
    int value;







|







2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
    }
    TclSmallFreeEx(interp, iterPtr);
    return result;
}

static int
ForCondCallback(
    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
    }
    TclSmallFreeEx(interp, iterPtr);
    return result;
}

static int
ForNextCallback(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    ForIterData *iterPtr = (ForIterData *)data[0];
    Tcl_Obj *next = iterPtr->next;








|







2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
    }
    TclSmallFreeEx(interp, iterPtr);
    return result;
}

static int
ForNextCallback(
    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

    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL);
    return result;
}

static int
ForPostNextCallback(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    ForIterData *iterPtr = (ForIterData *)data[0];

    if ((result != TCL_BREAK) && (result != TCL_OK)) {
	if (result == TCL_ERROR) {







|







2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678

    TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL);
    return result;
}

static int
ForPostNextCallback(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ForeachObjCmd(
    ClientData 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_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    return EachloopCmd(interp, TCL_EACH_KEEP_NONE, objc, objv);
}

int
Tcl_LmapObjCmd(
    ClientData 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_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;


    if (objc < 4 || (objc%2 != 0)) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"varList list ?varList list ...? command");
	return TCL_ERROR;
    }








|









|









|









|


















|
>







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ForeachObjCmd(
    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(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    return EachloopCmd(interp, TCL_EACH_KEEP_NONE, objc, objv);
}

int
Tcl_LmapObjCmd(
    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(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, 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
     *
     * 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)
	    + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *)));
    memset(statePtr, 0,
	    sizeof(struct ForeachState) + 3 * numLists * sizeof(int)
	    + 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->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++) {


	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]);




	if (statePtr->varcList[i] < 1) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s varlist is empty",
		    (statePtr->resultList != NULL ? "lmap" : "foreach")));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION",
		    (statePtr->resultList != NULL ? "LMAP" : "FOREACH"),
		    "NEEDVARS", NULL);
	    result = TCL_ERROR;
	    goto done;
	}















	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->argcList[i], &statePtr->argvList[i]);





	j = statePtr->argcList[i] / statePtr->varcList[i];
	if ((statePtr->argcList[i] % statePtr->varcList[i]) != 0) {
	    j++;
	}
	if (j > statePtr->maxj) {
	    statePtr->maxj = j;
	}







|


|





|


















>
>





|
|
>
>
>
>


|
|

|
|



>
>

>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|

>
>
|
>
>







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
     *
     * 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(Tcl_Size)
	    + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *)));
    memset(statePtr, 0,
	    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 = (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;
	}
	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")));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION",
		(statePtr->resultList != NULL ? "LMAP" : "FOREACH"),
		"NEEDVARS", (void *)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;
	    }
	    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

/*
 * Post-body processing handler.
 */

static int
ForeachLoopStep(
    ClientData 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));




	}
	break;
    case TCL_BREAK:
	result = TCL_OK;
	goto finish;
    case TCL_ERROR:
	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(







|
















|
|
>
>
>
>







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

/*
 * Post-body processing handler.
 */

static int
ForeachLoopStep(
    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) {
	    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
 */

static inline int
ForeachAssignments(
    Tcl_Interp *interp,
    struct ForeachState *statePtr)
{
    int i, v, k;

    Tcl_Obj *valuePtr, *varValuePtr;

    for (i=0 ; i<statePtr->numLists ; i++) {



	for (v=0 ; v<statePtr->varcList[i] ; v++) {
	    k = statePtr->index[i]++;

	    if (k < statePtr->argcList[i]) {









		valuePtr = statePtr->argvList[i][k];

	    } else {
		TclNewObj(valuePtr);	/* Empty string */
	    }

	    varValuePtr = Tcl_ObjSetVar2(interp, statePtr->varvList[i][v],
		    NULL, valuePtr, TCL_LEAVE_ERR_MSG);








|
>



>
>
>


<

>
>
>
>
>
>
>
>
>
|
>







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
 */

static inline int
ForeachAssignments(
    Tcl_Interp *interp,
    struct ForeachState *statePtr)
{
    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];
		}
	    } 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FormatObjCmd(
    TCL_UNUSED(ClientData),
    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) {







|







3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FormatObjCmd(
    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
/*
 * 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.
 *
 * 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"




/*
 * 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.
 */









|
|
|
|
|
|







>
>
>







1
2
3
4
5
6
7
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 © 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

/*
 * 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);

/*
 * 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
				 * 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. */
    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







|













|








|







46
47
48
49
50
51
52
53
54
55
56
57
58
59
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 *, 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. 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. */
    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
#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


















/*
 * 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;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#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 Sequence_Operators {
    LSEQ_DOTS, LSEQ_TO, LSEQ_COUNT, LSEQ_BY
} SequenceOperators;
static const char *const seq_step_keywords[] = {"by", NULL};
typedef enum Step_Operators {
    STEP_BY = 4
} SequenceByMode;
typedef enum Sequence_Decoded {
     NoneArg, NumericArg, RangeKeywordArg, ByKeywordArg
} 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
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},


    {"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},







>
>







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_IfObjCmd(
    ClientData 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_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);
	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);
    return Tcl_NRExprObj(interp, objv[1], boolObj);
}

static int
IfConditionCallback(
    ClientData 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]);







|









|










|











|





|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
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
Tcl_IfObjCmd(
    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(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", (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),
	    (void *) objv, INT2PTR(1), boolObj);
    return Tcl_NRExprObj(interp, objv[1], boolObj);
}

static int
IfConditionCallback(
    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
	 * (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);
	    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);







|







315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
	 * (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", (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
	    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);
	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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IncrObjCmd --







|
















|







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
	    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", (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", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IncrObjCmd --
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_IncrObjCmd(
    TCL_UNUSED(ClientData),
    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)) {







|







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_IncrObjCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoArgsCmd(
    TCL_UNUSED(ClientData),
    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);
	return TCL_ERROR;
    }

    /*
     * Build a return list containing the arguments.
     */








|




















|







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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoArgsCmd(
    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, (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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoBodyCmd(
    TCL_UNUSED(ClientData),
    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;

    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);
	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







|







|











|







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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoBodyCmd(
    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;
    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, (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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCmdCountCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;

    if (objc != 1) {







|







591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCmdCountCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCommandsCmd(
    TCL_UNUSED(ClientData),
    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;

    /*
     * Get the pattern and find the "effective namespace" in which to list
     * commands.
     */

    if (objc == 1) {







|














|







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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCommandsCmd(
    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;
    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
	 * 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();
		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);







|







709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
	 * 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);
		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
	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();
		    Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
		} else {
		    elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		}
		Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
	    }
	    entryPtr = Tcl_NextHashEntry(&search);







|







760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
	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);
		    TclNewObj(elemObjPtr);
		    Tcl_GetCommandFullName(interp, cmd, elemObjPtr);
		} else {
		    elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		}
		Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
	    }
	    entryPtr = Tcl_NextHashEntry(&search);
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCompleteCmd(
    TCL_UNUSED(ClientData),
    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;







|







910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCompleteCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoDefaultCmd(
    TCL_UNUSED(ClientData),
    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;







|







947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoDefaultCmd(
    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
    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);
	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));
	    } else {
		Tcl_Obj *nullObjPtr = Tcl_NewObj();


		valueObjPtr = Tcl_ObjSetVar2(interp, objv[3], NULL,
			nullObjPtr, TCL_LEAVE_ERR_MSG);
		if (valueObjPtr == NULL) {
		    return TCL_ERROR;
		}
		Tcl_SetObjResult(interp, Tcl_NewWideIntObj(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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoErrorStackCmd --







|













|

|
>






|








|







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
    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,
		(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_NewBooleanObj(1));
	    } else {
		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_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, (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoErrorStackCmd --
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoErrorStackCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Interp *target;
    Interp *iPtr;








|







1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoErrorStackCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoExistsCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *varName;
    Var *varPtr;








|







1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoExistsCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoFrameCmd(
    TCL_UNUSED(ClientData),
    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;







|







1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoFrameCmd(
    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;
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
    }

    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);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * Let us convert to relative so that we know how many levels to go back
     */







|







1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
    }

    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]), (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
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
				 * 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] = {







|







1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
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] = {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] = {
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385

	    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;

	    /*
	     * 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++) {







|







1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408

	    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;
	    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++) {
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoFunctionsCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *script;
    int code;








|







1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoFunctionsCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoHostnameCmd(
    TCL_UNUSED(ClientData),
    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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoLevelCmd --







|



















|







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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoHostnameCmd(
    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", (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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoLevelCmd(
    TCL_UNUSED(ClientData),
    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));
	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) {
		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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoLibraryCmd --







|







|


















|



















|







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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoLevelCmd(
    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((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 ((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]), (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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoLibraryCmd(
    TCL_UNUSED(ClientData),
    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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoLoadedCmd --







|



















|







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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoLibraryCmd(
    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", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * InfoLoadedCmd --
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoLoadedCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *interpName, *packageName;

    if (objc > 3) {







|







1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoLoadedCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *interpName, *packageName;

    if (objc > 3) {
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
	interpName = TclGetString(objv[1]);
    }
    if (objc < 3) {		/* Get loaded files in all packages. */
	packageName = NULL;
    } else {			/* Get pkgs just in specified interp. */
	packageName = TclGetString(objv[2]);
    }
    return TclGetLoadedPackagesEx(interp, interpName, packageName);
}

/*
 *----------------------------------------------------------------------
 *
 * InfoNameOfExecutableCmd --
 *







|







1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
	interpName = TclGetString(objv[1]);
    }
    if (objc < 3) {		/* Get loaded files in all packages. */
	packageName = NULL;
    } else {			/* Get pkgs just in specified interp. */
	packageName = TclGetString(objv[2]);
    }
    return TclGetLoadedLibraries(interp, interpName, packageName);
}

/*
 *----------------------------------------------------------------------
 *
 * InfoNameOfExecutableCmd --
 *
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoNameOfExecutableCmd(
    TCL_UNUSED(ClientData),
    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;







|







1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoNameOfExecutableCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoPatchLevelCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *patchlevel;

    if (objc != 1) {







|







1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoPatchLevelCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoProcsCmd(
    TCL_UNUSED(ClientData),
    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;








|







<
<
<







1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841



1842
1843
1844
1845
1846
1847
1848
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoProcsCmd(
    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;



    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
     * 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();
		    Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
			    elemObjPtr);
		} else {
		    elemObjPtr = Tcl_NewStringObj(simplePattern, -1);
		}
		Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
	    }
	}
    } 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();
			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;
}

/*







<














|








|
<
<
















|










<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
     * 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);

    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) {
		    TclNewObj(elemObjPtr);
		    Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
			    elemObjPtr);
		} else {
		    elemObjPtr = Tcl_NewStringObj(simplePattern, -1);
		}
		Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
	    }
	}
    } else {


	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) {
			TclNewObj(elemObjPtr);
			Tcl_GetCommandFullName(interp, (Tcl_Command) cmdPtr,
				elemObjPtr);
		    } else {
			elemObjPtr = Tcl_NewStringObj(cmdName, -1);
		    }
		    Tcl_ListObjAppendElement(interp, listPtr, elemObjPtr);
		}
	    }
	    entryPtr = Tcl_NextHashEntry(&search);
	}








































    }

    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
 *	script filename.
 *
 *----------------------------------------------------------------------
 */

static int
InfoScriptCmd(
    TCL_UNUSED(ClientData),
    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)) {







|







1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
 *	script filename.
 *
 *----------------------------------------------------------------------
 */

static int
InfoScriptCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoSharedlibCmd(
    TCL_UNUSED(ClientData),
    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;







|







2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoSharedlibCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoTclVersionCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *version;

    if (objc != 1) {







|







2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoTclVersionCmd(
    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
 *	message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCmdTypeCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Command command;

    if (objc != 2) {







|







2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
 *	message.
 *
 *----------------------------------------------------------------------
 */

static int
InfoCmdTypeCmd(
    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
    /*
     * 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);
    } else {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj(TclGetCommandTypeName(command), -1));
    }
    return TCL_OK;
}








|







2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
    /*
     * 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", (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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_JoinObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    size_t length;
    int listLen;
    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 (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 */

	Tcl_SetObjResult(interp, elemPtrs[0]);








	return TCL_OK;
    }

    joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
    Tcl_IncrRefCount(joinObjPtr);

    (void) TclGetStringFromObj(joinObjPtr, &length);
    if (length == 0) {
	resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
    } else {
	int i;

	resObjPtr = Tcl_NewObj();
	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.







|




|
|












>
>
>
>
>
>
>
|










>
|
>
>
>
>
>
>
>
>






|



|

|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_JoinObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    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;
	}
    } 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]);
	} 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);
    if (length == 0) {
	resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
    } else {
	Tcl_Size i;

	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LassignObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *listCopyPtr;
    Tcl_Obj **listObjv;		/* The contents of the list. */
    int listObjc;		/* The length of the list. */

    int code = TCL_OK;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "list ?varName ...?");
	return TCL_ERROR;
    }









    listCopyPtr = TclListObjCopy(interp, objv[1]);
    if (listCopyPtr == NULL) {

	return TCL_ERROR;
    }

    TclListObjGetElements(NULL, listCopyPtr, &listObjc, &listObjv);

    objc -= 2;
    objv += 2;


    while (code == TCL_OK && objc > 0 && listObjc > 0) {










	if (Tcl_ObjSetVar2(interp, *objv++, NULL, *listObjv++,
		TCL_LEAVE_ERR_MSG) == NULL) {

	    code = TCL_ERROR;
	}


	objc--;
	listObjc--;
    }

    if (code == TCL_OK && objc > 0) {

	Tcl_Obj *emptyObj;

	TclNewObj(emptyObj);
	Tcl_IncrRefCount(emptyObj);
	while (code == TCL_OK && objc-- > 0) {
	    if (Tcl_ObjSetVar2(interp, *objv++, NULL, emptyObj,
		    TCL_LEAVE_ERR_MSG) == NULL) {

		code = TCL_ERROR;
	    }
	}
	Tcl_DecrRefCount(emptyObj);
    }

    if (code == TCL_OK && listObjc > 0) {















	Tcl_SetObjResult(interp, Tcl_NewListObj(listObjc, listObjv));
    }

    Tcl_DecrRefCount(listCopyPtr);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * 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_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) {







|




|
<
|
>
|






>
>
>
>
>
>
>
>
|
|
>


|
<



>
>
|
>
>
>
>
>
>
>
>
>
>
|

>
|

>
>
|
|
|
<
|
>




|


>
|





|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


<
|

|



















|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LassignObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *listPtr;

    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.
     */
    listPtr = objv[1];

    if (TclListObjLength(interp, listPtr, &listObjc) != TCL_OK) {
	return TCL_ERROR;
    }
    origListObjc = listObjc;


    objc -= 2;
    objv += 2;
    for (i = 0; i < objc && i < listObjc; ++i) {
	Tcl_Obj *elemObj;

	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
	 * 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);
	    return TCL_ERROR;
	}
	Tcl_DecrRefCount(elemObj);
    }
    objc -= i;
    listObjc -= i;


    if (objc > 0) {
	/* Still some variables left to be assigned */
	Tcl_Obj *emptyObj;

	TclNewObj(emptyObj);
	Tcl_IncrRefCount(emptyObj);
	while (objc-- > 0) {
	    if (Tcl_ObjSetVar2(interp, *objv++, NULL, emptyObj,
		    TCL_LEAVE_ERR_MSG) == NULL) {
		Tcl_DecrRefCount(emptyObj);
		return TCL_ERROR;
	    }
	}
	Tcl_DecrRefCount(emptyObj);
    }

    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);
    }


    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(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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LinsertObjCmd(
    TCL_UNUSED(ClientData),
    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;

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "list index ?element ...?");
	return TCL_ERROR;
    }

    result = TclListObjLength(interp, objv[1], &len);







|





|
|







2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LinsertObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *listPtr;
    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
     * 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) {
	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);

    }

    if ((objc == 4) && (index == (size_t)len)) {
	/*
	 * Special case: insert one element at the end of the list.
	 */

	Tcl_ListObjAppendElement(NULL, listPtr, objv[3]);






    } else {
	if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, index, 0,
		(objc-3), &(objv[3]))) {



	    return TCL_ERROR;
	}
    }

    /*
     * Set the interpreter's object result.
     */







|











>


|




|
>
>
>
>
>
>



>
>
>







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
     * appended to the list.
     */

    result = TclGetIntForIndexM(interp, objv[2], /*end*/ len, &index);
    if (result != TCL_OK) {
	return result;
    }
    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 == len)) {
	/*
	 * Special case: insert one element at the end of the list.
	 */

	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ListObjCmd(
    TCL_UNUSED(ClientData),
    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.







|







2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ListObjCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LlengthObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* Argument objects. */
{

    int listLen, result;


    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.
     */


    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(listLen));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LpopObjCmd --







|





>
|
>
















>
|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LlengthObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* Argument objects. */
{
    Tcl_Size listLen;
    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, 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LpopObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* Argument objects. */
{
    int listLen, result;

    Tcl_Obj *elemPtr, *stored;
    Tcl_Obj *listPtr, **elemPtrs;

    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);
    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"
		"OUTOFRANGE", NULL);
	    return TCL_ERROR;
	}
	elemPtr = elemPtrs[listLen - 1];





	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);

	}
	result = Tcl_ListObjReplace(interp, listPtr, listLen - 1, 1, 0, NULL);
	if (result != TCL_OK) {



	    return result;
	}

	Tcl_IncrRefCount(listPtr);



    } else {
	listPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL);

	if (listPtr == NULL) {



	    return TCL_ERROR;



	}
    }

    stored = Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG);
    Tcl_DecrRefCount(listPtr);
    if (stored == NULL) {
	return TCL_ERROR;
    }

    return TCL_OK;
}








|





|
>

|











|















|


|
>
>
>
>
>



















>



>
>
>


>
|
>
>
>
|
|
|
|
>
>
>

>
>
>




<







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LpopObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* Argument objects. */
{
    Tcl_Size listLen;
    int copied = 0, result;
    Tcl_Obj *elemPtr, *stored;
    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 = 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"
		"OUTOFRANGE", (char *)NULL);
	    return TCL_ERROR;
	}

	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_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);

    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LrangeObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* Argument objects. */
{
    int listLen, result;
    size_t 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) {







|





|
|
<







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* Argument objects. */
{
    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

    result = TclGetIntForIndexM(interp, objv[3], /*endValue*/ listLen - 1,
	    &last);
    if (result != TCL_OK) {
	return result;
    }





    Tcl_SetObjResult(interp, TclListObjRange(objv[1], first, last));










    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LremoveObjCmd --







>
>
>
>
|
>
>
>
>
>
>
>
>
>
>







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, 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
 */

static int
LremoveIndexCompare(
    const void *el1Ptr,
    const void *el2Ptr)
{
    size_t idx1 = *((const size_t *) el1Ptr);
    size_t idx2 = *((const size_t *) el2Ptr);

    /*
     * This will put the larger element first.
     */

    return (idx1 < idx2) ? 1 : (idx1 > idx2) ? -1 : 0;
}

int
Tcl_LremoveObjCmd(
    TCL_UNUSED(ClientData),
    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_Obj *listObj;


    /*
     * 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));
    for (i = 2; i < objc; i++) {
	if (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1,
		&idxv[i - 2]) != TCL_OK) {
	    Tcl_Free(idxv);
	    return TCL_ERROR;

	}
    }

    /*
     * 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);
    }

    /*
     * Make our working copy, then do the actual removes piecemeal.
     */

    if (Tcl_IsShared(listObj)) {
	listObj = TclListObjCopy(NULL, listObj);

    }
    num = 0;
    first = listLen;
    for (i = 0, prevIdx = -1 ; i < idxc ; i++) {
	int idx = idxv[i];

	/*
	 * Repeated index and sanity check.
	 */

	if (idx == prevIdx) {
	    continue;







|
|










|




|
|

>




















|

|
|
<
|
>









|








>




|







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)
{
    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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 = (Tcl_Size *)Tcl_Alloc((objc - 2) * sizeof(*idxv));
    for (i = 2; i < objc; i++) {
	status = (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1,
		&idxv[i - 2]) != TCL_OK);

	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(*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++) {
	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
	    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);



	    listLen -= num;
	    num = 1;
	    first = idx;
	}
    }
    if (num != 0) {
	(void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);



    }
    Tcl_Free(idxv);



    Tcl_SetObjResult(interp, listObj);


    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LrepeatObjCmd --
 *







|
>
>
>






|
>
>
>
|
<
>
>
>

>
>
|







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.
	     */

	    status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
	    if (status != TCL_OK) {
		goto done;
	    }
	    listLen -= num;
	    num = 1;
	    first = idx;
	}
    }
    if (num != 0) {
	status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
	if (status != TCL_OK) {
	    if (copied) {
		Tcl_DecrRefCount(listObj);
	    }

	    goto done;
	}
    }
    Tcl_SetObjResult(interp, listObj);
done:
    Tcl_Free(idxv);
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LrepeatObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* The argument objects. */
{
    int elementCount, i, 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)) {
	return TCL_ERROR;
    }
    if (elementCount < 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad count \"%d\": must be integer >= 0", elementCount));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPEAT", "NEGARG",
		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);
	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);








	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;

	for (i=0 ; i<elementCount ; i++) {
	    for (j=0 ; j<objc ; j++) {
		Tcl_IncrRefCount(objv[j]);
		dataArray[k++] = objv[j];
	    }
	}







|





|
>











|




|

|














|
|











|
>
>
>
>
>
>
>
|
<
<


















|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,		/* Number of arguments. */
    Tcl_Obj *const objv[])
				/* The argument objects. */
{
    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 != TclGetWideIntFromObj(interp, objv[1], &elementCount)) {
	return TCL_ERROR;
    }
    if (elementCount < 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"bad count \"%" TCL_LL_MODIFIER "d\": must be integer >= 0", elementCount));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LREPEAT", "NEGARG",
		(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 (%" 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) {
	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;
	}


    }

    /*
     * 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 {
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LreplaceObjCmd(
    TCL_UNUSED(ClientData),
    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;

    if (objc < 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"list first last ?element ...?");
	return TCL_ERROR;
    }








|





|
|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *listPtr;
    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
    }

    result = TclGetIntForIndexM(interp, objv[3], /*end*/ listLen-1, &last);
    if (result != TCL_OK) {
	return result;
    }

    if (first == TCL_INDEX_NONE) {
	first = 0;
    } else if (first > (size_t)listLen) {
	first = listLen;
    }

    if (last + 1 > (size_t)listLen) {
	last = listLen - 1;
    }
    if (first + 1 <= last + 1) {
	numToDelete = last - first + 1;
    } 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".







|

|



|


|
|







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 < 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 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
     * 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)) {

	return TCL_ERROR;
    }

    /*
     * Set the interpreter's object result.
     */








>







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LreverseObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tcl_Obj **elemv;
    int elemc, i, j;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "list");
	return TCL_ERROR;
    }
    if (TclListObjGetElements(interp, objv[1], &elemc, &elemv) != 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 (Tcl_IsShared(objv[1])
	    || (ListRepPtr(objv[1])->refCount > 1)) {	/* Bug 1675044 */
	Tcl_Obj *resultObj, **dataArray;
	List *listRepPtr;

	resultObj = Tcl_NewListObj(elemc, NULL);
	listRepPtr = ListRepPtr(resultObj);


	listRepPtr->elemCount = elemc;
	dataArray = &listRepPtr->elements;






	for (i=0,j=elemc-1 ; i<elemc ; i++,j--) {
	    dataArray[j] = elemv[i];
	    Tcl_IncrRefCount(elemv[i]);
	}

	Tcl_SetObjResult(interp, resultObj);







|





|





|
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>
>
|
>

|

|


|
>
>
|
|
>
>
>
>
>







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    Tcl_Obj **elemv;
    Tcl_Size elemc, i, j;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "list");
	return TCL_ERROR;
    }

    /*
     *  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])
	    || ListObjRepIsShared(objv[1])) { /* Bug 1675044 */
	Tcl_Obj *resultObj, **dataArray;
	ListRep listRep;

	resultObj = Tcl_NewListObj(elemc, NULL);

	/* 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LsearchObjCmd(
    TCL_UNUSED(ClientData),
    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 allocatedIndexVector = 0;
    int dataType, isIncreasing;
    Tcl_WideInt patWide, objWide, wide;
    int allMatches, inlineReturn, negatedMatch, returnSubindices, noCase;
    double patDouble, objDouble;
    SortInfo sortInfo;
    Tcl_Obj *patObj, **listv, *listPtr, *startPtr, *itemPtr;
    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
    };
    enum modes {
	EXACT, GLOB, REGEXP, SORTED
    };
    enum modes mode;

    mode = GLOB;
    dataType = ASCII;







|





|
>
|

|
|



|


















|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    const char *bytes, *patternBytes;
    int match, result=TCL_OK, bisect;
    Tcl_Size i, length = 0, listc, elemLen, start, index;
    Tcl_Size groupOffset, lower, upper;
    int allocatedIndexVector = 0;
    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 = 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

    if (objc < 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-option value ...? list pattern");
	return TCL_ERROR;
    }

    for (i = 1; i < objc-2; i++) {

	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index)
		!= TCL_OK) {
	    result = TCL_ERROR;
	    goto done;
	}
	switch ((enum lsearchoptions) index) {
	case LSEARCH_ALL:		/* -all */
	    allMatches = 1;
	    break;
	case LSEARCH_ASCII:		/* -ascii */
	    dataType = ASCII;
	    break;
	case LSEARCH_BISECT:		/* -bisect */







>
|




|







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, &idx)
		!= TCL_OK) {
	    result = TCL_ERROR;
	    goto done;
	}
	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
	    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);
		result = TCL_ERROR;
		goto done;
	    }
	    i++;
	    if (objv[i] == objv[objc - 2]) {
		/*
		 * Take copy to prevent shimmering problems. Note that it does







|







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", (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
	    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);
		result = TCL_ERROR;
		goto done;
	    }
	    if (Tcl_GetWideIntFromObj(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);
		result = TCL_ERROR;
		goto done;
	    }
	    groupSize = wide;
	    i++;
	    break;
	case LSEARCH_INDEX: {		/* -index */
	    Tcl_Obj **indices;
	    int 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);
		result = TCL_ERROR;
		goto done;
	    }

	    /*
	     * Store the extracted indices for processing by sublist
	     * extraction. Note that we don't do this using objects because







|



|







|








|









|







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", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    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", (char *)NULL);
		result = TCL_ERROR;
		goto done;
	    }
	    groupSize = wide;
	    i++;
	    break;
	case LSEARCH_INDEX: {		/* -index */
	    Tcl_Obj **indices;
	    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", (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
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
		    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"
			    "OUTOFRANGE", NULL);
		    result = TCL_ERROR;
		}
		if (result == TCL_ERROR) {
		    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
			    "\n    (-index option item number %d)", 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);
	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);
	result = TCL_ERROR;
	goto done;
    }

    if (mode == REGEXP) {
	/*
	 * We can shimmer regexp/list if listv[i] == pattern, so get the







|




|

















|








|







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
		    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"
			    "OUTOFRANGE", (char *)NULL);
		    result = TCL_ERROR;
		}
		if (result == TCL_ERROR) {
		    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
			    "\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", (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", (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

    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);
	    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) {
		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);
		result = TCL_ERROR;
		goto done;
	    }
	    if (sortInfo.indexc == 1) {
		sortInfo.indexc = 0;
		sortInfo.indexv = NULL;
	    } else {







|










|




|







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

    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",
		    (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 < 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", (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
	}

	/*
	 * 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 (allMatches || inlineReturn) {
		Tcl_ResetResult(interp);
	    } else {
		TclNewIndexObj(itemPtr, TCL_INDEX_NONE);
		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) {
	case ASCII:
	case DICTIONARY:
	    patternBytes = TclGetStringFromObj(patObj, &length);
	    break;
	case INTEGER:
	    result = TclGetWideIntFromObj(interp, patObj, &patWide);
	    if (result != TCL_OK) {







|



|

















|







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
	}

	/*
	 * 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 >= listc) {
	    if (allMatches || inlineReturn) {
		Tcl_ResetResult(interp);
	    } else {
		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 (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

	/*
	 * With -stride, lower, upper and i are kept as multiples of groupSize.
	 */

	lower = start - groupSize;
	upper = listc;

	while (lower + groupSize != upper && sortInfo.resultCode == TCL_OK) {
	    i = (lower + upper)/2;
	    i -= i % groupSize;




	    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) {
	    case ASCII:
		bytes = TclGetString(itemPtr);
		match = strCmpFn(patternBytes, bytes);
		break;
	    case DICTIONARY:
		bytes = TclGetString(itemPtr);
		match = DictionaryCompare(patternBytes, bytes);







>



>
>
>
>









|







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

	/*
	 * 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 (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
	 */

	if (allMatches) {
	    listPtr = Tcl_NewListObj(0, NULL);
	}
	for (i = start; i < listc; i += groupSize) {
	    match = 0;



	    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) {
		case ASCII:
		    bytes = TclGetStringFromObj(itemPtr, &elemLen);
		    if (length == elemLen) {
			/*
			 * This split allows for more optimal compilation of
			 * memcmp/strcasecmp.
			 */







>
>
>
















|







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
	 */

	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 (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
		break;
	    } else if (inlineReturn) {
		/*
		 * Note that these appends are not expected to fail.
		 */

		if (returnSubindices && (sortInfo.indexc != 0)) {

		    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 {

		    itemPtr = listv[i];
		    Tcl_ListObjAppendElement(interp, listPtr, itemPtr);
		}
	    } else if (returnSubindices) {
		int 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));
	    }
	}
    }




    /*
     * Return everything or a single value.
     */

    if (allMatches) {
	Tcl_SetObjResult(interp, listPtr);
    } else if (!inlineReturn) {
	if (returnSubindices) {
	    int 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);







>







>




|















>
>
>








|







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
		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) {
		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) {
	    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
    result = TCL_OK;

    /*
     * Cleanup the index list array.
     */

  done:



    if (startPtr != NULL) {
	Tcl_DecrRefCount(startPtr);
    }
    if (allocatedIndexVector) {
	TclStackFree(interp, sortInfo.indexv);
    }
    return result;
}









































































































































































































































































































































































































/*
 *----------------------------------------------------------------------
 *
 * 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_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. */








>
>
>








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















|







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
    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, if supplied.
 */

static SequenceDecoded
SequenceIdentifyArgument(
     Tcl_Interp *interp,        /* for error reporting  */
     Tcl_Obj *argPtr,           /* Argument to decode   */
     Tcl_Obj **numValuePtr,     /* Return numeric value */
     int *keywordIndexPtr)      /* Return keyword enum  */
{
    int status;
    SequenceOperators opmode;
    SequenceByMode bymode;
    void *clientData;

    status = Tcl_GetNumberFromObj(NULL, argPtr, &clientData, keywordIndexPtr);
    if (status == TCL_OK) {
	if (numValuePtr) {
	    *numValuePtr = argPtr;
	}
	return NumericArg;
    } else {
	/* Check for an index expression */
	long value;
	double dvalue;
	Tcl_Obj *exprValueObj;
	int keyword;
	Tcl_InterpState savedstate;
	savedstate = Tcl_SaveInterpState(interp, status);
	if (Tcl_ExprLongObj(interp, argPtr, &value) != TCL_OK) {
	    status = Tcl_RestoreInterpState(interp, savedstate);
	    exprValueObj = argPtr;
	} else {
	    // Determine if expression is double or int
	    if (Tcl_ExprDoubleObj(interp, argPtr, &dvalue) != TCL_OK) {
		keyword = TCL_NUMBER_INT;
		exprValueObj = argPtr;
	    } else {
		if (floor(dvalue) == dvalue) {
		    TclNewIntObj(exprValueObj, value);
		    keyword = TCL_NUMBER_INT;
		} else {
		    TclNewDoubleObj(exprValueObj, dvalue);
		    keyword = TCL_NUMBER_DOUBLE;
		}
	    }
	    status = Tcl_RestoreInterpState(interp, savedstate);
	    if (numValuePtr) {
		*numValuePtr = exprValueObj;
	    }
	    if (keywordIndexPtr) {
		*keywordIndexPtr = keyword ;// type of expression result
	    }
	    return NumericArg;
	}
    }

    status = Tcl_GetIndexFromObj(NULL, argPtr, seq_operations,
				 "range operation", 0, &opmode);
    if (status == TCL_OK) {
	if (keywordIndexPtr) {
	    *keywordIndexPtr = opmode;
	}
	return RangeKeywordArg;
    }

    status = Tcl_GetIndexFromObj(NULL, argPtr, seq_step_keywords,
				 "step keyword", 0, &bymode);
    if (status == TCL_OK) {
	if (keywordIndexPtr) {
	    *keywordIndexPtr = bymode;
	}
	return ByKeywordArg;
    }
    return NoneArg;
}

/*
 *----------------------------------------------------------------------
 *
 * 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, useDoubles = 0;
    Tcl_Obj *arithSeriesPtr;
    SequenceOperators opmode;
    SequenceDecoded decoded;
    int i, arg_key = 0, value_i = 0;
    // Default constants
    Tcl_Obj *zero = Tcl_NewIntObj(0);
    Tcl_Obj *one = Tcl_NewIntObj(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 */
	 arg_key=0;
    } else for (i=1; i<objc; i++) {
	 arg_key = (arg_key * 10);
	 numValues[value_i] = NULL;
	 decoded = SequenceIdentifyArgument(interp, objv[i], &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:
	      arg_key += NumericArg;
	      numValues[value_i] = numberObj;
	      Tcl_IncrRefCount(numValues[value_i]);
	      values[value_i] = keyword;  // This is the TCL_NUMBER_* value
	      useDoubles = useDoubles ? useDoubles : keyword == TCL_NUMBER_DOUBLE;
	      value_i++;
	      break;

	 case RangeKeywordArg:
	      arg_key += RangeKeywordArg;
	      values[value_i] = keyword;
	      value_i++;
	      break;

	 case ByKeywordArg:
	      arg_key += ByKeywordArg;
	      values[value_i] = keyword;
	      value_i++;
	      break;

	 default:
	      arg_key += 9; // Error state
	      value_i++;
	      break;
	 }
    }

    /*
     * The key encoding defines a valid set of arguments, or indicates an
     * error condition; process the values accordningly.
     */
    switch (arg_key) {

/*    No argument */
    case 0:
	 Tcl_WrongNumArgs(interp, 1, objv,
	     "n ??op? n ??by? n??");
	 goto done;
	 break;

/*    lseq n */
    case 1:
	start = zero;
	elementCount = numValues[0];
	end = NULL;
	step = one;
	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;

/*    Error cases: incomplete arguments */
    case 12:
	 opmode = (SequenceOperators)values[1]; goto KeywordError; break;
    case 112:
	 opmode = (SequenceOperators)values[2]; goto KeywordError; break;
    case 1212:
	 opmode = (SequenceOperators)values[3]; goto KeywordError; break;
    KeywordError:
	 switch (opmode) {
	 case LSEQ_DOTS:
	 case LSEQ_TO:
	      Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		  "missing \"to\" value."));
	      break;
	 case LSEQ_COUNT:
	      Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		  "missing \"count\" value."));
	      break;
	 case LSEQ_BY:
	      Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		  "missing \"by\" value."));
	      break;
	 }
	 goto done;
	 break;

/*    All other argument errors */
    default:
	 Tcl_WrongNumArgs(interp, 1, objv, "n ??op? n ??by? n??");
	 goto done;
	 break;
    }

    /*
     * Success!  Now lets create the series object.
     */
    status = TclNewArithSeriesObj(interp, &arithSeriesPtr,
		  useDoubles, start, end, step, elementCount);

    if (status == TCL_OK) {
	Tcl_SetObjResult(interp, arithSeriesPtr);
    }

 done:
    // Free number arguments.
    while (--value_i>=0) {
	if (numValues[value_i]) {
	    Tcl_DecrRefCount(numValues[value_i]);
	}
    }

    // Free constants
    Tcl_DecrRefCount(zero);
    Tcl_DecrRefCount(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(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
     * 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 {







	finalValuePtr = TclLsetFlat(interp, listPtr, objc-3, objv+2,
		objv[objc-1]);

    }

    /*
     * If substitution has failed, bail out.
     */

    if (finalValuePtr == NULL) {







>
>
>
>
>
>
>
|
|
>







4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
     * 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]);
	}
    }

    /*
     * 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LsortObjCmd(
    TCL_UNUSED(ClientData),
    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 sortMode = SORTMODE_ASCII;
    int group, allocatedIndexVector = 0;
    size_t j, idx, groupSize, groupOffset;
    Tcl_WideInt wide;
    Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
    size_t 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
    };

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-option value ...? list");
	return TCL_ERROR;
    }

    /*







|




|


|
|

|



















|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LsortObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    int indices, nocase = 0, indexc;
    int sortMode = SORTMODE_ASCII;
    int group, allocatedIndexVector = 0;
    Tcl_Size j, idx, groupOffset, length;
    Tcl_WideInt wide, groupSize;
    Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
    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
    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) {
	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);
		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_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);
		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++) {
		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"
			    "OUTOFRANGE", NULL);
		    result = TCL_ERROR;
		}
		if (result == TCL_ERROR) {
		    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
			    "\n    (-index option item number %" TCL_Z_MODIFIER "d)", j));
		    sortInfo.resultCode = TCL_ERROR;
		    goto done;
		}
	    }
	    indexPtr = objv[i+1];
	    i++;
	    break;







|








|

















|






|

















|









|




|







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
    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 (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", (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: {
	    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", (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<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"
			    "OUTOFRANGE", (char *)NULL);
		    result = TCL_ERROR;
		}
		if (result == TCL_ERROR) {
		    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
			    "\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
	    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);
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    if (Tcl_GetWideIntFromObj(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);
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    groupSize = wide;
	    group = 1;
	    i++;
	    break;







|



|







|







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
	    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", (char *)NULL);
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    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", (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
	    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++) {
	    /* 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];







|







4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
	    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<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

	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;
    }





    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);
	    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) {
		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);
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    if (sortInfo.indexc == 1) {
		sortInfo.indexc = 0;
		sortInfo.indexv = NULL;
	    } else {







<
<








>
>
>
>
|

>















|











|




|







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

	newCommandPtr = Tcl_DuplicateObj(cmdPtr);
	TclNewObj(newObjPtr);
	Tcl_IncrRefCount(newCommandPtr);
	if (Tcl_ListObjAppendElement(interp, newCommandPtr, newObjPtr)
		!= TCL_OK) {
	    TclDecrRefCount(newCommandPtr);


	    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,
	    &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",
		    (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 < 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", (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
    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);
	sortInfo.resultCode = TCL_ERROR;
	goto done;
    }

    for (i=0; i < length; i++) {
	idx = groupSize * i + groupOffset;
	if (indexc) {







|
|







4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
    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 %" 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
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    elementArray[i].collationKey.wideValue = a;
	} else if (sortMode == SORTMODE_REAL) {
	    double a;

	    if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr,
		    &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
	 * 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);







|
<




















|







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
		sortInfo.resultCode = TCL_ERROR;
		goto done;
	    }
	    elementArray[i].collationKey.wideValue = a;
	} else if (sortMode == SORTMODE_REAL) {
	    double a;

	    if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr, &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 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
    }

    /*
     * Now store the sorted elements in the result list.
     */

    if (sortInfo.resultCode == TCL_OK) {
	List *listRepPtr;
	Tcl_Obj **newArray, *objPtr;

	resultPtr = Tcl_NewListObj(sortInfo.numElements * groupSize, NULL);
	listRepPtr = ListRepPtr(resultPtr);
	newArray = &listRepPtr->elements;
	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;







|



|
|







4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
    }

    /*
     * Now store the sorted elements in the result list.
     */

    if (sortInfo.resultCode == TCL_OK) {
	ListRep listRep;
	Tcl_Obj **newArray, *objPtr;

	resultPtr = Tcl_NewListObj(sortInfo.numElements * groupSize, NULL);
	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
	} else {
	    for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) {
		objPtr = elementPtr->payload.objPtr;
		newArray[i++] = objPtr;
		Tcl_IncrRefCount(objPtr);
	    }
	}

	listRepPtr->elemCount = i;



	Tcl_SetObjResult(interp, resultPtr);
    }

  done:
    if (sortMode == SORTMODE_COMMAND) {
	TclDecrRefCount(sortInfo.compareCmdPtr);
	TclDecrRefCount(listObj);







>
|
>
>
>







4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
	} else {
	    for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) {
		objPtr = elementPtr->payload.objPtr;
		newArray[i++] = objPtr;
		Tcl_IncrRefCount(objPtr);
	    }
	}
	listRep.storePtr->numUsed = 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
	    Tcl_Free(elementArray);
	} else {
	    free((char *)elementArray);
	}
    }
    return sortInfo.resultCode;
}














































































































/*
 *----------------------------------------------------------------------
 *
 * MergeLists -
 *
 *	This procedure combines two sorted lists of SortElement structures







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    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
 *
 * 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
 *	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.
 *







|







5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
 *
 * SortCompare --
 *
 *	This procedure is invoked by MergeLists to determine the proper
 *	ordering between two elements.
 *
 * Results:
 *	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
	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_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.
	     */







|







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];
	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.
	     */
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
	 */

	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);
	    infoPtr->resultCode = TCL_ERROR;
	    return 0;
	}
    }
    if (!infoPtr->isIncreasing) {
	order = -order;
    }







|







5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
	 */

	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", (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
    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 */
		&& 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.
	     */







|







5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
    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 */
		&& 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
	/*
	 * 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);

	    /*
	     * Convert both chars to lower for the comparison, because
	     * dictionary sorts are case insensitve. 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 {







|
|



|







5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
	/*
	 * 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 += TclUtfToUniChar(left, &uniLeft);
	    right += TclUtfToUniChar(right, &uniRight);

	    /*
	     * Convert both chars to lower for the comparison, because
	     * 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

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;

    /*
     * 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++) {

	int listLen, index;
	Tcl_Obj *currentObj;

	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) {
		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);
	    infoPtr->resultCode = TCL_ERROR;
	    return NULL;
	}
	objPtr = currentObj;


    }
    return objPtr;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * tab-width: 8
 * End:
 */







|















>
|
|














|










|




>
>












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

static Tcl_Obj *
SelectObjFromSublist(
    Tcl_Obj *objPtr,		/* Obj to select sublist from. */
    SortInfo *infoPtr)		/* Information passed from the top-level
				 * "lsearch" or "lsort" command. */
{
    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 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 == 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", (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
/*
 * 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.
 *
 * 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"


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);




/*
 * 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) */
;

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PwdObjCmd --
 *








|
|
|
|
|









>









>
>
>







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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 © 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) */
;

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PwdObjCmd --
 *
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PwdObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *retVal;

    if (objc != 1) {







|







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PwdObjCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RegexpObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t 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
    };

    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) {
	case REGEXP_ALL:
	    all = 1;
	    break;
	case REGEXP_INDICES:
	    indices = 1;
	    break;
	case REGEXP_INLINE:







|




|













|










<









|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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;


	name = TclGetString(objv[i]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", TCL_EXACT,
		&index) != TCL_OK) {
	    goto optionError;
	}
	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
	case REGEXP_LINESTOP:
	    cflags |= TCL_REG_NLSTOP;
	    break;
	case REGEXP_LINEANCHOR:
	    cflags |= TCL_REG_NLANCH;
	    break;
	case REGEXP_START: {
	    size_t temp;
	    if (++i >= objc) {
		goto endOfForLoop;
	    }
	    if (TclGetIntForIndexM(interp, objv[i], (size_t)WIDE_MAX - 1, &temp) != TCL_OK) {
		goto optionError;
	    }
	    if (startIndex) {
		Tcl_DecrRefCount(startIndex);
	    }
	    startIndex = objv[i];
	    Tcl_IncrRefCount(startIndex);







|



|







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: {
	    Tcl_Size temp;
	    if (++i >= objc) {
		goto endOfForLoop;
	    }
	    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
     * 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);
	goto optionError;
    }

    /*
     * Handle the odd about case separately.
     */








|







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", (void *)NULL);
	goto optionError;
    }

    /*
     * Handle the odd about case separately.
     */

257
258
259
260
261
262
263
264
265
266
267
268
269
270
271

    objPtr = objv[1];
    stringLength = Tcl_GetCharLength(objPtr);

    if (startIndex) {
	TclGetIntForIndexM(interp, startIndex, stringLength, &offset);
	Tcl_DecrRefCount(startIndex);
	if (offset == TCL_INDEX_NONE) {
	    offset = TCL_INDEX_START;
	}
    }

    regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags);
    if (regExpr == NULL) {
	return TCL_ERROR;







|







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 < 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
	 * 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) {
	    eflags = TCL_REG_NOTBOL;
	} else if (Tcl_GetUniChar(objPtr, offset-1) == '\n') {
	    eflags = 0;
	} else {
	    eflags = TCL_REG_NOTBOL;
	}








|







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 > 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
	    /*
	     * It's the number of substitutions, plus one for the matchVar at
	     * index 0
	     */

	    objc = info.nsubs + 1;
	    if (all <= 1) {
		resultPtr = Tcl_NewObj();
	    }
	}
	for (i = 0; i < objc; i++) {
	    Tcl_Obj *newPtr;

	    if (indices) {
		size_t 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) {
		    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) {
			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) {
		    newPtr = Tcl_GetRange(objPtr,
			    offset + info.matches[i].start,
			    offset + info.matches[i].end - 1);
		} else {
		    newPtr = Tcl_NewObj();
		}
	    }
	    if (doinline) {
		if (Tcl_ListObjAppendElement(interp, resultPtr, newPtr)
			!= TCL_OK) {
		    Tcl_DecrRefCount(newPtr);
		    Tcl_DecrRefCount(resultPtr);







|






|







|








|












|




|







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) {
		TclNewObj(resultPtr);
	    }
	}
	for (i = 0; i < objc; i++) {
	    Tcl_Obj *newPtr;

	    if (indices) {
		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 >= 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 >= 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) && (info.matches[i].end > 0)) {
		    newPtr = Tcl_GetRange(objPtr,
			    offset + info.matches[i].start,
			    offset + info.matches[i].end - 1);
		} else {
		    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

	/*
	 * 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
	 * 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) {
	    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







|
















|







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 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 >= 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RegsubObjCmd(
    TCL_UNUSED(ClientData),
    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;
    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
    };

    cflags = TCL_REG_ADVANCED;
    all = 0;
    offset = TCL_INDEX_START;
    command = 0;
    resultPtr = NULL;

    for (idx = 1; idx < (size_t)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) {
	case REGSUB_ALL:
	    all = 1;
	    break;
	case REGSUB_NOCASE:
	    cflags |= TCL_REG_NOCASE;
	    break;
	case REGSUB_COMMAND:







|




|
|
|














|







|

<









|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 < objc; idx++) {
	const char *name;


	name = TclGetString(objv[idx]);
	if (name[0] != '-') {
	    break;
	}
	if (Tcl_GetIndexFromObj(interp, objv[idx], options, "option",
		TCL_EXACT, &index) != TCL_OK) {
	    goto optionError;
	}
	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
	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) {
		goto endOfForLoop;
	    }
	    if (TclGetIntForIndexM(interp, objv[idx], (size_t)WIDE_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) {
	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]);

	TclGetIntForIndexM(interp, startIndex, stringLength, &offset);
	Tcl_DecrRefCount(startIndex);
	if (offset == TCL_INDEX_NONE) {
	    offset = TCL_INDEX_START;
	}
    }

    if (all && (offset == TCL_INDEX_START) && (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;
	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);
	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);
		    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);
			p = wstring + slen;
		    } else {
			p += slen;
		    }
		    wstring = p - 1;

		    TclAppendUnicodeToObj(resultPtr, wsubspec, wsublen);
		    numMatches++;
		}
	    }
	    if (numMatches) {
		wlen    = wfirstChar + wlen - p;
		wstring = p;
	    }







|
|


|
















|













|



|
|



|







|








|
|
|













|
|















|






|







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: {
	    Tcl_Size temp;
	    if (++idx >= objc) {
		goto endOfForLoop;
	    }
	    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 (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) {
	Tcl_Size stringLength = Tcl_GetCharLength(objv[1]);

	TclGetIntForIndexM(interp, startIndex, stringLength, &offset);
	Tcl_DecrRefCount(startIndex);
	if (offset < 0) {
	    offset = 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.
	 */

	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 = 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++) {
		    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) {
			Tcl_AppendUnicodeToObj(resultPtr, p, wstring - p);
			p = wstring + slen;
		    } else {
			p += slen;
		    }
		    wstring = p - 1;

		    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
	/*
	 * 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) {
	    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);
	    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);
    if (objv[2] == objv[0]) {
	subPtr = Tcl_DuplicateObj(objv[2]);
    } else {
	subPtr = objv[2];
    }
    if (!command) {
	wsubspec = TclGetUnicodeFromObj(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







|







|
















|






|







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 (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", (void *)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 = Tcl_GetUnicodeFromObj(objPtr, &wlen);
    if (objv[2] == objv[0]) {
	subPtr = Tcl_DuplicateObj(objv[2]);
    } else {
	subPtr = objv[2];
    }
    if (!command) {
	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
	    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);
	    }
	}
	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);

	/*
	 * 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_ListObjGetElements(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)) {
		    args[idx + numParts] = Tcl_NewUnicodeObj(
			    wstring + offset + subStart, subEnd - subStart);
		} else {
		    args[idx + numParts] = Tcl_NewObj();
		}
		Tcl_IncrRefCount(args[idx + numParts]);
	    }







|












|










|

|







|







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.
		 */

		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;
	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;
	    Tcl_Size numArgs;

	    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 >= 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
	    Tcl_ResetResult(interp);

	    /*
	     * Refetch the unicode, in case the representation was smashed by
	     * the user code.
	     */

	    wstring = TclGetUnicodeFromObj(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);
		}
		offset++;
	    }
	    if (all) {
		continue;
	    } else {
		break;







|











|







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 = 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) {
		    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
		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,
			    wsrc - wfirstChar + 1);
		    *wsrc = '\\';
		    wfirstChar = wsrc + 2;
		    wsrc++;
		    continue;
		} else {
		    continue;
		}
	    } else {
		continue;
	    }

	    if (wfirstChar != wsrc) {
		TclAppendUnicodeToObj(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,
			    wstring + offset + subStart, subEnd - subStart);
		}
	    }

	    if (*wsrc == '\\') {
		wsrc++;
	    }
	    wfirstChar = wsrc + 1;
	}

	if (wfirstChar != wsrc) {
	    TclAppendUnicodeToObj(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);
	    }
	    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);
		}
		offset++;
	    }
	}
	if (!all) {
	    break;
	}







|













|






|
|











|









|











|







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;
		    Tcl_AppendUnicodeToObj(resultPtr, wfirstChar,
			    wsrc - wfirstChar + 1);
		    *wsrc = '\\';
		    wfirstChar = wsrc + 2;
		    wsrc++;
		    continue;
		} else {
		    continue;
		}
	    } else {
		continue;
	    }

	    if (wfirstChar != wsrc) {
		Tcl_AppendUnicodeToObj(resultPtr, wfirstChar,
			wsrc - wfirstChar);
	    }

	    if (idx <= info.nsubs) {
		subStart = info.matches[idx].start;
		subEnd = info.matches[idx].end;
		if ((subStart >= 0) && (subEnd >= 0)) {
		    Tcl_AppendUnicodeToObj(resultPtr,
			    wstring + offset + subStart, subEnd - subStart);
		}
	    }

	    if (*wsrc == '\\') {
		wsrc++;
	    }
	    wfirstChar = wsrc + 1;
	}

	if (wfirstChar != wsrc) {
	    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) {
		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) {
		    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
	 * 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);
    }
    if (objc == 4) {
	if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr,
		TCL_LEAVE_ERR_MSG) == NULL) {
	    result = TCL_ERROR;
	} else {
	    /*







|







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) {
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RenameObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *oldName, *newName;

    if (objc != 3) {







|







1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RenameObjCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ReturnObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int code, level;
    Tcl_Obj *returnOpts;








|







1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ReturnObjCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SourceObjCmd(
    ClientData 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_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");
	return TCL_ERROR;
    }

    fileName = objv[objc-1];

    if (objc == 4) {
	static const char *const options[] = {







|









|











|







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(
    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(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 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SplitObjCmd(
    TCL_UNUSED(ClientData),
    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_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();

    if (stringLen == 0) {
	/*
	 * Do nothing.
	 */
    } else if (splitCharLen == 0) {
	Tcl_HashTable charReuseTable;







|









|














|







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(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;
    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;
    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
	 * 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);
	    hPtr = Tcl_CreateHashEntry(&charReuseTable, INT2PTR(ch), &isNew);
	    if (isNew) {
		TclNewStringObj(objPtr, stringPtr, len);

		/*
		 * Don't need to fiddle with refcount...
		 */







|







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 = 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
	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
	 * 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;
	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);
	    for (p = splitChars; p < splitEnd; p += splitLen) {
		splitLen = TclUtfToUCS4(p, &splitChar);
		if (ch == splitChar) {
		    TclNewStringObj(objPtr, element, stringPtr - element);
		    Tcl_ListObjAppendElement(NULL, listPtr, objPtr);
		    element = stringPtr + len;
		    break;
		}
	    }







|












|










|

|







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
	 * 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;
	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 = TclUtfToUniChar(stringPtr, &ch);
	    for (p = splitChars; p < splitEnd; p += splitLen) {
		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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringFirstCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t 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;

	if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &start)) {
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, TclStringFirst(objv[1], objv[2], start));
    return TCL_OK;







|




|








|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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) {
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringLastCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t last = TCL_INDEX_END;

    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;

	if (TCL_OK != TclGetIntForIndexM(interp, objv[3], end, &last)) {
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, TclStringLast(objv[1], objv[2], last));
    return TCL_OK;







|




|








|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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) {
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringIndexCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t 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)) {
	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;
}

/*







|




|















|



















<
<
<







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 >= 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);



	    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringInsertCmd(
    TCL_UNUSED(ClientData),
    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_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) {
	index = TCL_INDEX_START;
    }
    if (index > length) {
	index = length;
    }

    outObj = TclStringReplace(interp, objv[1], index, 0, objv[3],







|




|
|












|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* Argument objects */
{
    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 < 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringIsCmd(
    TCL_UNUSED(ClientData),
    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;
    size_t failat = 0;
    size_t length1, length2;
    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
    };
    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
    };
    static const char *const isOptions[] = {
	"-strict", "-failindex", NULL
    };
    enum isOptionsEnum {
	OPT_STRICT, OPT_FAILIDX
    };

    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) {
	    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,
     * Tcl_Get*FromObj would do).
     */

    objPtr = objv[objc-1];

    /*
     * When entering here, result == 1 and failat == 0.
     */

    switch ((enum isClassesEnum) 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)
		&& (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;


	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;
	    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) {







|






|
<
|








|
|






|
|
|





|













<
<




|


















|









|












|
















|
>












|
<







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(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;

    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
    };
    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
    } 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++) {


	    if (Tcl_GetIndexFromObj(interp, objv[i], isOptions, "option", 0,
		    &idx2) != TCL_OK) {
		return TCL_ERROR;
	    }
	    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 occurring (as, for example,
     * Tcl_Get*FromObj would do).
     */

    objPtr = objv[objc-1];

    /*
     * When entering here, result == 1 and failat == 0.
     */

    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 (!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;
	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;
	    Tcl_Size lenRemain, 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
	}
	break;
    }
    case STR_IS_DIGIT:
	chcomp = Tcl_UniCharIsDigit;
	break;
    case STR_IS_DOUBLE: {
	if (TclHasIntRep(objPtr, &tclDoubleType) ||
		TclHasIntRep(objPtr, &tclIntType) ||
		TclHasIntRep(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,
		(const char **) &stop, 0) != TCL_OK) {
	    result = 0;
	    failat = 0;
	} else {
	    failat = stop - string1;
	    if (stop < end) {
		result = 0;
		TclFreeIntRep(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)) {
	    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,
		(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);
	    }
	} else {
	    /*
	     * No prefix is a valid integer. Fail at beginning.
	     */

	    result = 0;







|
|
|










|







|









|
|










|

















|







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 (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, TCL_INDEX_NONE,
		(const char **) &stop, 0) != TCL_OK) {
	    result = 0;
	    failat = 0;
	} else {
	    failat = stop - string1;
	    if (stop < end) {
		result = 0;
		TclFreeInternalRep(objPtr);
	    }
	}
	break;
    }
    case STR_IS_GRAPH:
	chcomp = Tcl_UniCharIsGraph;
	break;
    case STR_IS_INT:
    case STR_IS_ENTIER:
	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, 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;
		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
	     * 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,
		(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);
	    }
	} else {
	    /*
	     * No prefix is a valid integer. Fail at beginning.
	     */

	    failat = 0;







|



















|







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, 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;
		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
	    /*
	     * 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;
	    const char *p;

	    string1 = TclGetStringFromObj(objPtr, &length1);
	    end = string1 + length1;
	    failat = -1;
	    for (p=string1, lenRemain=length1; lenRemain > 0;
		    p=nextElem, lenRemain=end-nextElem) {







|
|







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;
	    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
	    }
	    goto str_is_done;
	}
	end = string1 + length1;
	for (; string1 < end; string1 += length2, failat++) {
	    int ucs4;

	    length2 = TclUtfToUCS4(string1, &ucs4);
	    if (!chcomp(ucs4)) {
		result = 0;
		break;
	    }
	}
    }








|







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 = 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringMapCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t 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);
	    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;
	Tcl_DictSearch search;

	/*
	 * We know the type exactly, so all dict operations will succeed for
	 * sure. This shortens this code quite a bit.
	 */








|




|




















|










|
>
|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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, (void *)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])
	    && 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
	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;
	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);
	    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);
    if (length1 == 0) {
	/*
	 * Empty input string, just stop now.
	 */

	goto done;
    }
    end = ustring1 + length1;

    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;
	int u2lc;
	Tcl_UniChar *mapString;

	ustring2 = TclGetUnicodeFromObj(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);
	    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);
			p = ustring1 + length2;
		    } else {
			p += length2;
		    }
		    ustring1 = p - 1;

		    TclAppendUnicodeToObj(resultPtr, mapString, mapLen);
		}
	    }
	}
    } else {
	Tcl_UniChar **mapStrings;
	size_t *mapLens;
	int *u2lc = 0;

	/*
	 * 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);
	if (nocase) {
	    u2lc = (int *)TclStackAlloc(interp, mapElemc * sizeof(int));
	}
	for (index = 0; index < mapElemc; index++) {
	    mapStrings[index] = TclGetUnicodeFromObj(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) ||
			!strCmpFn(ustring2, ustring1, length2))) {
		    if (p != ustring1) {
			/*
			 * Put the skipped chars onto the result first.
			 */

			TclAppendUnicodeToObj(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.
		     */

		    TclAppendUnicodeToObj(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_SetObjResult(interp, resultPtr);
  done:
    if (mapWithDict) {
	TclStackFree(interp, mapElemv);
    }
    if (copySource) {







|




















|















|









|















|



|








|







|






|





|



|






|




|
















|






|












|


|
















|







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 {
	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", (void *)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 = Tcl_GetUnicodeFromObj(sourceObj, &length1);
    if (length1 == 0) {
	/*
	 * Empty input string, just stop now.
	 */

	goto done;
    }
    end = ustring1 + length1;

    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.
	 */

	Tcl_Size mapLen;
	int u2lc;
	Tcl_UniChar *mapString;

	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 = 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) {
			Tcl_AppendUnicodeToObj(resultPtr, p, ustring1-p);
			p = ustring1 + length2;
		    } else {
			p += length2;
		    }
		    ustring1 = p - 1;

		    Tcl_AppendUnicodeToObj(resultPtr, mapString, mapLen);
		}
	    }
	}
    } else {
	Tcl_UniChar **mapStrings;
	Tcl_Size *mapLens;
	int *u2lc = 0;

	/*
	 * 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 = (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] = 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. */
			((end-ustring1) >= length2) && ((length2 == 1) ||
			!strCmpFn(ustring2, ustring1, length2))) {
		    if (p != ustring1) {
			/*
			 * Put the skipped chars onto the result first.
			 */

			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.
		     */

		    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.
	 */

	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringMatchCmd(
    TCL_UNUSED(ClientData),
    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;
	const char *string = TclGetStringFromObj(objv[1], &length);

	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);
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(
		TclStringMatchObj(objv[objc-1], objv[objc-2], nocase)));
    return TCL_OK;
}







|












|


<
|





|







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(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) {
	Tcl_Size length;
	const char *string = TclGetStringFromObj(objv[1], &length);


	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, (void *)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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringRangeCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t 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) {
	last = end;
    }
    if (last + 1 >= first + 1) {
	Tcl_SetObjResult(interp, Tcl_GetRange(objv[1], first, last));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|




|


















<
<
<
|
<
<
<







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 (last >= 0) {



	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringReptCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int 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) {
	return TCL_ERROR;
    }

    /*
     * Check for cases that allow us to skip copying stuff.
     */








|




|







|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_WideInt count;
    Tcl_Obj *resultPtr;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "string count");
	return TCL_ERROR;
    }

    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringRplcCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
	size_t 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 */
	/*
	 * 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) {
	    first = TCL_INDEX_START;
	}
	if (last + 1 > end + 1) {
	    last = end;
	}

	resultPtr = TclStringReplace(interp, objv[1], first,
		last + 1 - first, (objc == 5) ? objv[4] : NULL,
		TCL_STRING_IN_PLACE);




	Tcl_SetObjResult(interp, resultPtr);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|




|



















|
|
|










|


|







>
>
>







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 < 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 < 0) {
	    first = TCL_INDEX_START;
	}
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringRevCmd(
    TCL_UNUSED(ClientData),
    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;







|







2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringRevCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringStartCmd(
    TCL_UNUSED(ClientData),
    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;
    Tcl_Obj *obj;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "string index");
	return TCL_ERROR;
    }

    string = TclGetStringFromObj(objv[1], &length);
    numChars = Tcl_NumUtfChars(string, length) - 1;
    if (TclGetIntForIndexM(interp, objv[2], numChars, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    string = TclGetString(objv[1]);
    if (index + 1 > numChars + 1) {
	index = numChars;
    }
    cur = 0;
    if (index + 1 > 1) {
	p = Tcl_UtfAtIndex(string, index);

	TclUtfToUCS4(p, &ch);
	for (cur = index; cur != TCL_INDEX_NONE; cur--) {
	    int delta = 0;
	    const char *next;

	    if (!Tcl_UniCharIsWordChar(ch)) {
		break;
	    }

	    next = TclUtfPrev(p, string);
	    do {
		next += delta;

		delta = TclUtfToUCS4(next, &ch);
	    } while (next + delta < p);
	    p = next;
	}
	if (cur != index) {
	    cur += 1;
	}
    }







|





|
|







|
<
|


<
|
|


|
|

|


|





|


>
|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int ch;
    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 = Tcl_GetUnicodeFromObj(objv[1], &length);

    if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    if (index >= length) {
	index = length - 1;
    }
    cur = 0;
    if (index > 0) {
	p = &string[index];

	ch = *p;
	for (cur = index; cur != TCL_INDEX_NONE; cur--) {
	    int delta = 0;
	    const Tcl_UniChar *next;

	    if (!Tcl_UniCharIsWordChar(ch)) {
		break;
	    }

	    next = ((p > string) ? (p - 1) : p);
	    do {
		next += delta;
		ch = *next;
		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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringEndCmd(
    TCL_UNUSED(ClientData),
    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;
    Tcl_Obj *obj;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "string index");
	return TCL_ERROR;
    }

    string = TclGetStringFromObj(objv[1], &length);
    numChars = Tcl_NumUtfChars(string, length) - 1;
    if (TclGetIntForIndexM(interp, objv[2], numChars, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    string = TclGetStringFromObj(objv[1], &length);
    if (index == TCL_INDEX_NONE) {
	index = TCL_INDEX_START;
    }
    if (index + 1 <= numChars + 1) {
	p = Tcl_UtfAtIndex(string, index);
	end = string+length;
	for (cur = index; p < end; cur++) {
	    p += TclUtfToUCS4(p, &ch);
	    if (!Tcl_UniCharIsWordChar(ch)) {
		break;
	    }
	}
	if (cur == index) {
	    cur++;
	}
    } else {
	cur = numChars + 1;
    }
    TclNewIndexObj(obj, cur);
    Tcl_SetObjResult(interp, obj);
    return TCL_OK;
}

/*







|





|
|







|
<
|


<
|
|

|
|


|








|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int ch;
    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 = Tcl_GetUnicodeFromObj(objv[1], &length);

    if (TclGetIntForIndexM(interp, objv[2], length-1, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    if (index < 0) {
	index = 0;
    }
    if (index < length) {
	p = &string[index];
	end = string+length;
	for (cur = index; p < end; cur++) {
	    ch = *p++;
	    if (!Tcl_UniCharIsWordChar(ch)) {
		break;
	    }
	}
	if (cur == index) {
	    cur++;
	}
    } else {
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringEqualCmd(
    TCL_UNUSED(ClientData),
    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;


    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) {
		return TCL_ERROR;



	    }
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\": must be -nocase or -length",
		    string2));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option",
		    string2, 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);
    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(match ? 0 : 1));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|











|
|
>


















|

>
>
>






|










|







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(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;
    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 (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, (void *)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], 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringCmpCmd(
    TCL_UNUSED(ClientData),
    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;


    status = TclStringCmpOpts(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(
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects. */
    int *nocase,
    int *reqlength)
{
    int i;
    size_t length;
    const char *string;


    *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) {
		return TCL_ERROR;





	    }
	} else {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad option \"%s\": must be -nocase or -length",
		    string));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", "option",
		    string, NULL);
	    return TCL_ERROR;
	}
    }
    return TCL_OK;
}

/*







|










|
>

|











|




|


|

>

<


















|

>
>
>
>
>






|







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(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, status;
    Tcl_Size reqlength = -1;

    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
StringCmpOpts(
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[],	/* Argument objects. */
    int *nocase,
    Tcl_Size *reqlength)
{
    int i;
    Tcl_Size length;
    const char *string;
    Tcl_WideInt wreqlength = -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 (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, (void *)NULL);
	    return TCL_ERROR;
	}
    }
    return TCL_OK;
}

/*
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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *objResultPtr;

    if (objc < 2) {







|







2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringCatCmd(
    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

    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_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;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

















|







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;
}

/*
 *----------------------------------------------------------------------
 *






































 * 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(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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringLowerCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t 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;
	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 = 0;
	}
	last = first;

	if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
		&last) != TCL_OK)) {
	    return TCL_ERROR;
	}

	if (last + 1 >= length1 + 1) {
	    last = length1;
	}
	if (last + 1 < first + 1) {
	    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);







|




|

















|







|









|


|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 {
	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 < 0) {
	    first = 0;
	}
	last = first;

	if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
		&last) != TCL_OK)) {
	    return TCL_ERROR;
	}

	if (last >= length1) {
	    last = length1;
	}
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringUpperCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t 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;
	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;
	}
	last = first;

	if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
		&last) != TCL_OK)) {
	    return TCL_ERROR;
	}

	if (last + 1 >= length1 + 1) {
	    last = length1;
	}
	if (last + 1 < first + 1) {
	    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);







|




|

















|







|
|








|


|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 {
	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 < 0) {
	    first = 0;
	}
	last = first;

	if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
		&last) != TCL_OK)) {
	    return TCL_ERROR;
	}

	if (last >= length1) {
	    last = length1;
	}
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringTitleCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    size_t 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;
	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;
	}
	last = first;

	if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
		&last) != TCL_OK)) {
	    return TCL_ERROR;
	}

	if (last + 1 >= length1 + 1) {
	    last = length1;
	}
	if (last + 1 < first + 1) {
	    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);







|




|

















|







|
|








|


|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 {
	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 < 0) {
	    first = 0;
	}
	last = first;

	if ((objc == 4) && (TclGetIntForIndexM(interp, objv[3], length1,
		&last) != TCL_OK)) {
	    return TCL_ERROR;
	}

	if (last >= length1) {
	    last = length1;
	}
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringTrimCmd(
    TCL_UNUSED(ClientData),
    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;

    if (objc == 3) {
	string2 = TclGetStringFromObj(objv[2], &length2);
    } else if (objc == 2) {
	string2 = tclDefaultTrimSet;
	length2 = strlen(tclDefaultTrimSet);
    } else {







|





|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *string1, *string2;
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringTrimLCmd(
    TCL_UNUSED(ClientData),
    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;

    if (objc == 3) {
	string2 = TclGetStringFromObj(objv[2], &length2);
    } else if (objc == 2) {
	string2 = tclDefaultTrimSet;
	length2 = strlen(tclDefaultTrimSet);
    } else {







|






|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *string1, *string2;
    int trim;
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringTrimRCmd(
    TCL_UNUSED(ClientData),
    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;

    if (objc == 3) {
	string2 = TclGetStringFromObj(objv[2], &length2);
    } else if (objc == 2) {
	string2 = tclDefaultTrimSet;
	length2 = strlen(tclDefaultTrimSet);
    } else {







|






|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *string1, *string2;
    int trim;
    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
 */

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},







<







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[] = {

	{"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
 *
 *----------------------------------------------------------------------
 */

int
TclSubstOptions(
    Tcl_Interp *interp,
    int numOpts,
    Tcl_Obj *const opts[],
    int *flagPtr)
{
    static const char *const substOptions[] = {
	"-nobackslashes", "-nocommands", "-novariables", NULL
    };
    enum {







|







3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
 *
 *----------------------------------------------------------------------
 */

int
TclSubstOptions(
    Tcl_Interp *interp,
    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
    }
    *flagPtr = flags;
    return TCL_OK;
}

int
Tcl_SubstObjCmd(
    ClientData 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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int flags;

    if (objc < 2) {







|









|







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(
    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(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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SwitchObjCmd(
    ClientData 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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, index, mode, foundmode, splitObjs, numMatchesSaved;
    int noCase;
    size_t 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. */







|








|




|

|







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(
    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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, mode, foundmode, splitObjs, numMatchesSaved;
    int noCase;
    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
    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
    };
    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) {
	    /*
	     * General options.
	     */

	case OPT_LAST:
	    i++;
	    goto finishedOptions;







|

















|







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 (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
		 * 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);
		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);
		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);
		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);
	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);
	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;


	blist = objv[0];
	if (TclListObjGetElements(interp, objv[0], &objc, &listv) != TCL_OK) {
	    return TCL_ERROR;
	}

	/*
	 * Ensure that the list is non-empty.
	 */

	if (objc < 1) {
	    Tcl_WrongNumArgs(interp, 1, savedObjv,
		    "?-option ...? string {?pattern body ...? ?default body?}");
	    return TCL_ERROR;
	}




	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);

	/*
	 * 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);
		    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);
	return TCL_ERROR;
    }

    for (i = 0; i < objc; i += 2) {
	/*
	 * See if the pattern matches the string.
	 */







|


















|












|


















|






|




















>


|







|




>
>
>
>














|

















|


















|







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", (void *)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", (void *)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", (void *)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", (void *)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", (void *)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 (TclListObjLength(interp, objv[0], &listc) != TCL_OK) {
	    return TCL_ERROR;
	}

	/*
	 * Ensure that the list is non-empty.
	 */

	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",
		(void *)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?", (void *)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", (void *)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
	    TclNewObj(indicesObj);
	}

	for (j=0 ; j<=info.nsubs ; j++) {
	    if (indexVarObj != NULL) {
		Tcl_Obj *rangeObjAry[2];

		if (info.matches[j].end + 1 > 1) {
		    TclNewIndexObj(rangeObjAry[0], info.matches[j].start);
		    TclNewIndexObj(rangeObjAry[1], info.matches[j].end-1);
		} else {
		    TclNewIndexObj(rangeObjAry[1], TCL_INDEX_NONE);
		    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;


		substringObj = Tcl_GetRange(stringObj,
			info.matches[j].start, info.matches[j].end-1);




		/*
		 * Never fails; the object is always clean at this point.
		 */

		Tcl_ListObjAppendElement(NULL, matchesObj, substringObj);
	    }







|



|














>
|
|
>
>
>







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 > 0) {
		    TclNewIndexObj(rangeObjAry[0], info.matches[j].start);
		    TclNewIndexObj(rangeObjAry[1], info.matches[j].end-1);
		} else {
		    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);
		} 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
	     * 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->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->nline = objc;
	    for (k=0; k < objc; k++) {
		ctxPtr->line[k] = -1;
	    }
	}
    }

    for (j = i + 1; ; j += 2) {
	if (j >= (size_t)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);
    return TclNREvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j);
}

static int
SwitchPostProc(
    ClientData 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);

    /*
     * Clean up TIP 280 context information
     */

    if (splitObjs) {
	Tcl_Free(ctxPtr->line);







|













|








|

















|





|









|







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 = (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 = (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 >= 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), (void *)pattern);
    return TclNREvalObjEx(interp, objv[j], 0, ctxPtr, splitObjs ? j : bidx+j);
}

static int
SwitchPostProc(
    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];
    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
    }

    /*
     * Generate an error message if necessary.
     */

    if (result == TCL_ERROR) {
	unsigned limit = 50;
	int overflow = (patternLength > limit);

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (\"%.*s%s\" arm line %d)",
		(overflow ? limit : (unsigned)patternLength), pattern,
		(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
    }
    TclStackFree(interp, ctxPtr);
    return result;
}

/*







|




|







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) {
	int limit = 50;
	int overflow = (patternLength > limit);

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (\"%.*s%s\" arm line %d)",
		(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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ThrowObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *options;
    int 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) {
	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);
	return TCL_ERROR;
    }

    /*
     * Now prepare the result options dictionary. We use the list API as it is
     * slightly more convenient.
     */







|





|










|





|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *options;
    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 (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",
		(void *)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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TimeObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TimeObjCmd(
    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
#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);
    } else {
	objs[0] = Tcl_NewDoubleObj(totalMicroSec/count);
    }

    /*
     * Construct the result as a list because many programs have always parsed
     * as such (extracting the first element, typically).
     */








|

|







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]
	 */

	TclNewIntObj(objs[0], (count <= 0) ? 0 : (Tcl_WideInt)totalMicroSec);
    } else {
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TimeRateObjCmd(
    TCL_UNUSED(ClientData),
    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 */







|







4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TimeRateObjCmd(
    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
    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;

	if (Tcl_GetIndexFromObj(NULL, objv[i], options, "option", TCL_EXACT,
		&index) != TCL_OK) {
	    break;
	}
	if (index == TMRT_LAST) {
	    i++;
	    break;
	}
	switch ((enum timeRateOptionsEnum)index) {
	case TMRT_EV_DIRECT:
	    direct = objv[i];
	    break;
	case TMRT_OVERHEAD:
	    if (++i >= objc - 1) {
		goto usage;
	    }







|









|







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++) {
	enum timeRateOptionsEnum index;

	if (Tcl_GetIndexFromObj(NULL, objv[i], options, "option", TCL_EXACT,
		&index) != TCL_OK) {
	    break;
	}
	if (index == TMRT_LAST) {
	    i++;
	    break;
	}
	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
	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);

	if (result != TCL_OK) {
	    return result;
	}
	if (i < objc) {	/* max-count*/
	    Tcl_WideInt v;

	    result = Tcl_GetWideIntFromObj(interp, objv[i], &v);
	    if (result != TCL_OK) {
		return result;
	    }
	    maxcnt = (v > 0) ? v : 0;
	}
    }








|
>






|







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 = 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 = 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
	    /*
	     * Calibration: obtaining new measurement overhead.
	     */

	    if (measureOverhead > ((double) usec) / count) {
		measureOverhead = ((double) usec) / count;
	    }
	    objs[0] = Tcl_NewDoubleObj(measureOverhead);
	    TclNewLiteralStringObj(objs[1], "\xC2\xB5s/#-overhead"); /* mics */
	    objs += 2;
	}

	val = usec / count;		/* microsecs per iteration */
	if (val >= 1000000) {
	    TclNewIntObj(objs[0], val);







|







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;
	    }
	    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TryObjCmd(
    ClientData 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_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;

    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();
    bodyShared = 0;
    haveHandlers = 0;
    for (i=2 ; i<objc ; i++) {
	int 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) {
	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);
		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);
		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);
		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);
		return TCL_ERROR;
	    }
	    code = 1;
	    if (Tcl_ListObjLength(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);
		return TCL_ERROR;
	    }
	    info[2] = objv[i+1];

	commonHandler:
	    if (Tcl_ListObjLength(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 */







|









|





|
>



















|



|







|






|







|












|


















|



|





|





|







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(
    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(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, 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];
    TclNewObj(handlersObj);
    bodyShared = 0;
    haveHandlers = 0;
    for (i=2 ; i<objc ; i++) {
	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 (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", (void *)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", (void *)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", (void *)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", (void *)NULL);
		return TCL_ERROR;
	    }
	    code = 1;
	    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", (void *)NULL);
		return TCL_ERROR;
	    }
	    info[2] = objv[i+1];

	commonHandler:
	    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
	}
    }
    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);
	return TCL_ERROR;
    }
    if (!haveHandlers) {
	Tcl_DecrRefCount(handlersObj);
	handlersObj = NULL;
    }

    /*
     * Execute the body.
     */

    Tcl_NRAddCallback(interp, TryPostBody, handlersObj, finallyObj,
	    (ClientData)objv, INT2PTR(objc));
    return TclNREvalObjEx(interp, bodyObj, 0,
	    ((Interp *) interp)->cmdFramePtr, 1);
}

/*
 *----------------------------------------------------------------------
 *







|












|







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",
		(void *)NULL);
	return TCL_ERROR;
    }
    if (!haveHandlers) {
	Tcl_DecrRefCount(handlersObj);
	handlersObj = NULL;
    }

    /*
     * Execute the body.
     */

    Tcl_NRAddCallback(interp, TryPostBody, handlersObj, finallyObj,
	    (void *)objv, INT2PTR(objc));
    return TclNREvalObjEx(interp, bodyObj, 0,
	    ((Interp *) interp)->cmdFramePtr, 1);
}

/*
 *----------------------------------------------------------------------
 *
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
 *	command.
 *
 *----------------------------------------------------------------------
 */

static int
TryPostBody(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultObj, *options, *handlersObj, *finallyObj, *cmdObj, **objv;
    int i, code, objc;
    int numHandlers = 0;

    handlersObj = (Tcl_Obj *)data[0];
    finallyObj = (Tcl_Obj *)data[1];
    objv = (Tcl_Obj **)data[2];
    objc = PTR2INT(data[3]);

    cmdObj = objv[0];







|




|
|







4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
 *	command.
 *
 *----------------------------------------------------------------------
 */

static int
TryPostBody(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultObj, *options, *handlersObj, *finallyObj, *cmdObj, **objv;
    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
     * Handle the results.
     */

    if (handlersObj != NULL) {
	int found = 0;
	Tcl_Obj **handlers, **info;

	Tcl_ListObjGetElements(NULL, handlersObj, &numHandlers, &handlers);
	for (i=0 ; i<numHandlers ; i++) {
	    Tcl_Obj *handlerBodyObj;
	    int numElems = 0;

	    Tcl_ListObjGetElements(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;

		    TclNewLiteralStringObj(errorCodeName, "-errorcode");
		    Tcl_DictObjGet(NULL, options, errorCodeName, &errcode);
		    Tcl_DecrRefCount(errorCodeName);
		    Tcl_ListObjGetElements(NULL, info[2], &len1, &bits1);
		    if (Tcl_ListObjGetElements(NULL, errcode, &len2,
			    &bits2) != TCL_OK) {
			continue;
		    }
		    if (len2 < len1) {
			continue;
		    }
		    for (j=0 ; j<len1 ; j++) {







|


|

|















|




|
|







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
     * Handle the results.
     */

    if (handlersObj != NULL) {
	int found = 0;
	Tcl_Obj **handlers, **info;

	TclListObjGetElements(NULL, handlersObj, &numHandlers, &handlers);
	for (i=0 ; i<numHandlers ; i++) {
	    Tcl_Obj *handlerBodyObj;
	    Tcl_Size numElems = 0;

	    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;
		    Tcl_Size len1, len2, j;

		    TclNewLiteralStringObj(errorCodeName, "-errorcode");
		    Tcl_DictObjGet(NULL, options, errorCodeName, &errcode);
		    Tcl_DecrRefCount(errorCodeName);
		    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++) {
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
	    /*
	     * 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);
	    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);







|







4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
	    /*
	     * Bind the variables. We already know this is a list of variable
	     * names, but it might be empty.
	     */

	    Tcl_ResetResult(interp);
	    result = TCL_ERROR;
	    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
 *	'try' command.
 *
 *----------------------------------------------------------------------
 */

static int
TryPostHandler(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultObj, *cmdObj, *options, *handlerKindObj, **objv;
    Tcl_Obj *finallyObj;
    int finally;

    objv = (Tcl_Obj **)data[0];
    options = (Tcl_Obj *)data[1];
    handlerKindObj = (Tcl_Obj *)data[2];
    finally = PTR2INT(data[3]);

    cmdObj = objv[0];
    finallyObj = finally ? objv[finally] : 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(







|





|




|


|







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
 *	'try' command.
 *
 *----------------------------------------------------------------------
 */

static int
TryPostHandler(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultObj, *cmdObj, *options, *handlerKindObj, **objv;
    Tcl_Obj *finallyObj;
    int finallyIndex;

    objv = (Tcl_Obj **)data[0];
    options = (Tcl_Obj *)data[1];
    handlerKindObj = (Tcl_Obj *)data[2];
    finallyIndex = PTR2INT(data[3]);

    cmdObj = objv[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
	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);
    }

    /*
     * Install the correct result/options into the interpreter and clean up
     * any temporary storage.
     */








|







5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
	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,
		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
 *	of a 'try' command.
 *
 *----------------------------------------------------------------------
 */

static int
TryPostFinal(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *resultObj, *options, *cmdObj;

    resultObj = (Tcl_Obj *)data[0];
    options = (Tcl_Obj *)data[1];







|







5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
 *	of a 'try' command.
 *
 *----------------------------------------------------------------------
 */

static int
TryPostFinal(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WhileObjCmd(
    ClientData 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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    ForIterData *iterPtr;

    if (objc != 3) {







|









|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WhileObjCmd(
    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(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
 */

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_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);
    const char *element = NULL, *next = NULL;
    ContLineLoc *clLocPtr = TclContinuationsGet(listObj);
    int *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);







|
|
|





|


|







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
 */

void
TclListLines(
    Tcl_Obj *listObj,		/* Pointer to obj holding a string with list
				 * structure. Assumed to be valid. Assumed to
				 * contain n elements. */
    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;
    Tcl_Size i, length = strlen(listStr);
    const char *element = NULL, *next = NULL;
    ContLineLoc *clLocPtr = TclContinuationsGet(listObj);
    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
/*
 * 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.
 *
 * 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"






|
|
|
|







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 © 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
 */

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
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *varTokenPtr, *valueTokenPtr;
    int isScalar, localIndex, numWords, i;








|







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 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
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileArray*Cmd --
 *
 *	Functions called to compile "array" sucommands.
 *
 * 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







|







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileArray*Cmd --
 *
 *	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
}

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
				 * 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 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);
    isDataEven = (isDataValid && (len & 1) == 0);

    /*
     * Special case: literal odd-length argument is always an error.
     */

    if (isDataValid && !isDataEven) {







|






|
>














|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
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 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;
    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
	    && TclListObjLength(NULL, literalObj, &len) == TCL_OK);
    isDataEven = (isDataValid && (len & 1) == 0);

    /*
     * Special case: literal odd-length argument is always an error.
     */

    if (isDataValid && !isDataEven) {
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
     */

    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]->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.







|







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
     */

    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(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
}

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
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
    int isScalar, localIndex;








|







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 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
    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)) {
	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)) {
	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) {
	resultNameTokenPtr = TokenAfter(cmdTokenPtr);
	/* DGP */
	resultIndex = LocalScalarFromToken(resultNameTokenPtr, envPtr);
	if (resultIndex < 0) {
	    return TCL_ERROR;
	}








|








|










|







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 (((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 (((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 ((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
     * 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.
     */

    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);







|







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 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);
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
	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) {
	    return TCL_ERROR;
	} else if (!strncmp(tokenPtr[1].start, "-microseconds",
			    tokenPtr[1].size)) {
	    TclEmitInstInt1(INST_CLOCK_READ, 1, envPtr);
	    break;
	} else if (!strncmp(tokenPtr[1].start, "-milliseconds",
			    tokenPtr[1].size)) {
	    TclEmitInstInt1(INST_CLOCK_READ, 2, envPtr);
	    break;
	} else {
	    return TCL_ERROR;
	}
    default:
	return TCL_ERROR;







|
|


|



|







768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
	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) {
	    return TCL_ERROR;
	} else if (!strncmp(tokenPtr[1].start, "-microseconds",
		tokenPtr[1].size)) {
	    TclEmitInstInt1(INST_CLOCK_READ, 1, envPtr);
	    break;
	} else if (!strncmp(tokenPtr[1].start, "-milliseconds",
		tokenPtr[1].size)) {
	    TclEmitInstInt1(INST_CLOCK_READ, 2, envPtr);
	    break;
	} else {
	    return TCL_ERROR;
	}
    default:
	return TCL_ERROR;
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
 */

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
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    if (parsePtr->numWords != 1) {
	return TCL_ERROR;
    }








|







813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
 */

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 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

    /*
     * 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++) {
	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_ListObjGetElements(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++) {
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);
    }

    TclEmitInstInt4(	INST_CONCAT_STK, i-1,		envPtr);

    return TCL_OK;
}















































































/*
 *----------------------------------------------------------------------
 *
 * TclCompileContinueCmd --
 *
 *	Procedure called to compile the "continue" command.







|













<
|

|












|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

    /*
     * 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 < (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;

	Tcl_Size len, slen;

	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 < (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
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileDict*Cmd --
 *
 *	Functions called to compile "dict" sucommands.
 *
 * 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







|







1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileDict*Cmd --
 *
 *	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
    int i, dictVarIndex;
    Tcl_Token *varTokenPtr;

    /*
     * There must be at least one argument after the command.
     */

    if (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++) {
	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);
    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
				 * 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) {
	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;
	int code;
	Tcl_Token *incrTokenPtr;
	Tcl_Obj *intObj;

	incrTokenPtr = TokenAfter(keyTokenPtr);
	if (incrTokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    return TclCompileBasic2Or3ArgCmd(interp, parsePtr,cmdPtr, envPtr);







|




















|








|










|











|











|







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
    int i, dictVarIndex;
    Tcl_Token *varTokenPtr;

    /*
     * There must be at least one argument after the command.
     */

    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< (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, (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 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 ((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;
	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

    /*
     * 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) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);

    /*
     * Only compile this because we need INST_DICT_GET anyway.
     */

    for (i=1 ; i<parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    TclEmitInstInt4(INST_DICT_GET, parsePtr->numWords-2, envPtr);
    TclAdjustStackDepth(-1, envPtr);
    return TCL_OK;
}

int
TclCompileDictGetWithDefaultCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */







|








|



|







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

    /*
     * 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 ((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<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    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
    int i;

    /*
     * There must be at least three arguments after the command.
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords < 4) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);

    for (i=1 ; i<parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    TclEmitInstInt4(INST_DICT_GET_DEF, parsePtr->numWords-3, envPtr);
    TclAdjustStackDepth(-2, envPtr);
    return TCL_OK;
}

int
TclCompileDictExistsCmd(
    Tcl_Interp *interp,		/* Used for looking up stuff. */







|




|



|







1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
    int i;

    /*
     * There must be at least three arguments after the command.
     */

    /* TODO: Consider support for compiling expanded args. */
    if ((int)parsePtr->numWords < 4) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);

    for (i=1 ; i<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    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

    /*
     * 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) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);

    /*
     * Now we do the code generation.
     */

    for (i=1 ; i<parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    TclEmitInstInt4(INST_DICT_EXISTS, 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
				 * 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) {
	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++) {
	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);
    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
				 * 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;

    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) {
	TclNewObj(keyObj);
	Tcl_IncrRefCount(keyObj);
	if (!TclWordKnownAtCompileTime(tokenPtr, keyObj)) {
	    Tcl_DecrRefCount(keyObj);
	    Tcl_DecrRefCount(dictObj);
	    goto nonConstant;
	}







|








|



|









|













|



















|








|









|









|












|







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

    /*
     * 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 ((int)parsePtr->numWords < 3) {
	return TCL_ERROR;
    }
    tokenPtr = TokenAfter(parsePtr->tokenPtr);

    /*
     * Now we do the code generation.
     */

    for (i=1 ; i<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    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 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 ((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<(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, (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 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;
    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<(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
	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) {
	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
				 * 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) {
	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);







|




















|













|







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
	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<(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 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 ((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
    /*
     * 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++) {
	/*
	 * Get the dictionary, and merge its pairs into the first dict (using
	 * a small loop).
	 */

	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);







|







1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
    /*
     * 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<(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
}

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
				 * 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
				 * 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
				 * 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;

    int numVars, 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.







|












|












|










>
|







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
}

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 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 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 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 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
    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.
     */

    TclAdjustStackDepth(-1, envPtr);
    ExceptionRangeTarget(envPtr, catchRange, catchOffset);
    TclEmitOpcode(	INST_PUSH_RETURN_OPTIONS,		envPtr);
    TclEmitOpcode(	INST_PUSH_RESULT,			envPtr);
    TclEmitOpcode(	INST_END_CATCH,				envPtr);







|







1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
    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 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
}

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
				 * 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) {
	return TCL_ERROR;
    }

    /*
     * Parse the command. Expect the following:
     *   dict update <lit(eral)> <any> <lit> ?<any> <lit> ...? <lit>
     */

    if ((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







|













|








|







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
}

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 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 ((int)parsePtr->numWords < 5) {
	return TCL_ERROR;
    }

    /*
     * Parse the command. Expect the following:
     *   dict update <lit(eral)> <any> <lit> ?<any> <lit> ...? <lit>
     */

    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

    /*
     * 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->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) {
	    goto failedUpdateInfoAssembly;
	}
	tokenPtr = TokenAfter(tokenPtr);
    }
    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	goto failedUpdateInfoAssembly;
    }







|


















|







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

    /*
     * 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(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] == 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
     */

    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
     */

    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);







|







1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
     */

    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 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
}

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
				 * 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
     * speed quite so much. ;-)
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords<4 || 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++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    if (parsePtr->numWords > 4) {
	TclEmitInstInt1(INST_STR_CONCAT1, 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
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *varTokenPtr, *keyTokenPtr, *valueTokenPtr;
    int dictVarIndex;








|









|




|


















|



|
|















|







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
}

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 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
     * (arbitrary) safe limit; anyone exceeding it should stop worrying about
     * speed quite so much. ;-)
     */

    /* TODO: Consider support for compiling expanded args. */
    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<(int)parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    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 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
}

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
				 * 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) {
	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++) {
	tokenPtr = TokenAfter(tokenPtr);
    }
    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
    }

    /*







|















|










|







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
}

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 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 ((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<(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
	}
    }

    /*
     * Determine if we're manipulating a dict in a simple local variable.
     */

    gotPath = (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++) {
		    CompileWord(envPtr, tokenPtr, interp, i);
		    tokenPtr = TokenAfter(tokenPtr);
		}
		TclEmitInstInt4(INST_LIST, 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.







|


















|



|







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
	}
    }

    /*
     * Determine if we're manipulating a dict in a simple local variable.
     */

    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<(int)parsePtr->numWords-1 ; i++) {
		    CompileWord(envPtr, tokenPtr, interp, i);
		    tokenPtr = TokenAfter(tokenPtr);
		}
		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
	} else {
	    if (gotPath) {
		/*
		 * Case: Path into dict in non-simple var with empty body.
		 */

		tokenPtr = varTokenPtr;
		for (i=1 ; i<parsePtr->numWords-1 ; i++) {
		    CompileWord(envPtr, tokenPtr, interp, i);
		    tokenPtr = TokenAfter(tokenPtr);
		}
		TclEmitInstInt4(INST_LIST, 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 {
		/*







|



|







2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
	} else {
	    if (gotPath) {
		/*
		 * Case: Path into dict in non-simple var with empty body.
		 */

		tokenPtr = varTokenPtr;
		for (i=1 ; i<(int)parsePtr->numWords-1 ; i++) {
		    CompileWord(envPtr, tokenPtr, interp, i);
		    tokenPtr = TokenAfter(tokenPtr);
		}
		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

    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++) {
	    CompileWord(envPtr, tokenPtr, interp, i);
	    tokenPtr = TokenAfter(tokenPtr);
	}
	TclEmitInstInt4(	INST_LIST, 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);







|



|







2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246

    if (dictVar == -1) {
	CompileWord(envPtr, varTokenPtr, interp, 1);
	Emit14Inst(		INST_STORE_SCALAR, varNameTmp,	envPtr);
    }
    tokenPtr = TokenAfter(varTokenPtr);
    if (gotPath) {
	for (i=2 ; i<(int)parsePtr->numWords-1 ; i++) {
	    CompileWord(envPtr, tokenPtr, interp, i);
	    tokenPtr = TokenAfter(tokenPtr);
	}
	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
    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) {
	Emit14Inst(		INST_LOAD_SCALAR, pathTmp,	envPtr);
    } else {
	PushStringLiteral(envPtr, "");
    }
    Emit14Inst(			INST_LOAD_SCALAR, keysTmp,	envPtr);
    if (dictVar == -1) {
	TclEmitOpcode(		INST_DICT_RECOMBINE_STK,	envPtr);







|







2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
    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 ((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
 *	FreeDictUpdateInfo: releases memory
 *	PrintDictUpdateInfo: none
 *	DisassembleDictUpdateInfo: none
 *
 *----------------------------------------------------------------------
 */

static ClientData
DupDictUpdateInfo(
    ClientData clientData)
{
    DictUpdateInfo *dui1Ptr, *dui2Ptr;
    size_t len;

    dui1Ptr = (DictUpdateInfo *)clientData;
    len = offsetof(DictUpdateInfo, varIndices) + sizeof(int) * dui1Ptr->length;
    dui2Ptr = (DictUpdateInfo *)Tcl_Alloc(len);
    memcpy(dui2Ptr, dui1Ptr, len);
    return dui2Ptr;
}

static void
FreeDictUpdateInfo(
    ClientData clientData)
{
    Tcl_Free(clientData);
}

static void
PrintDictUpdateInfo(
    ClientData clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
{
    DictUpdateInfo *duiPtr = (DictUpdateInfo *)clientData;
    size_t i;

    for (i=0 ; i<duiPtr->length ; i++) {
	if (i) {
	    Tcl_AppendToObj(appendObj, ", ", -1);
	}
	Tcl_AppendPrintfToObj(appendObj, "%%v%u", duiPtr->varIndices[i]);
    }
}

static void
DisassembleDictUpdateInfo(
    ClientData clientData,
    Tcl_Obj *dictObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
{
    DictUpdateInfo *duiPtr = (DictUpdateInfo *)clientData;
    size_t i;
    Tcl_Obj *variables;

    TclNewObj(variables);
    for (i=0 ; i<duiPtr->length ; i++) {
	Tcl_ListObjAppendElement(NULL, variables,
		Tcl_NewWideIntObj(duiPtr->varIndices[i]));
    }







|

|





|







|






|


|


|





|





|


|


|







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
 *	FreeDictUpdateInfo: releases memory
 *	PrintDictUpdateInfo: none
 *	DisassembleDictUpdateInfo: none
 *
 *----------------------------------------------------------------------
 */

static void *
DupDictUpdateInfo(
    void *clientData)
{
    DictUpdateInfo *dui1Ptr, *dui2Ptr;
    size_t len;

    dui1Ptr = (DictUpdateInfo *)clientData;
    len = offsetof(DictUpdateInfo, varIndices) + sizeof(size_t) * dui1Ptr->length;
    dui2Ptr = (DictUpdateInfo *)Tcl_Alloc(len);
    memcpy(dui2Ptr, dui1Ptr, len);
    return dui2Ptr;
}

static void
FreeDictUpdateInfo(
    void *clientData)
{
    Tcl_Free(clientData);
}

static void
PrintDictUpdateInfo(
    void *clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(size_t))
{
    DictUpdateInfo *duiPtr = (DictUpdateInfo *)clientData;
    Tcl_Size i;

    for (i=0 ; i<duiPtr->length ; i++) {
	if (i) {
	    Tcl_AppendToObj(appendObj, ", ", -1);
	}
	Tcl_AppendPrintfToObj(appendObj, "%%v%" TCL_Z_MODIFIER "u", duiPtr->varIndices[i]);
    }
}

static void
DisassembleDictUpdateInfo(
    void *clientData,
    Tcl_Obj *dictObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(size_t))
{
    DictUpdateInfo *duiPtr = (DictUpdateInfo *)clientData;
    Tcl_Size i;
    Tcl_Obj *variables;

    TclNewObj(variables);
    for (i=0 ; i<duiPtr->length ; i++) {
	Tcl_ListObjAppendElement(NULL, variables,
		Tcl_NewWideIntObj(duiPtr->varIndices[i]));
    }
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;

    /*
     * General syntax: [error message ?errorInfo? ?errorCode?]
     */

    if (parsePtr->numWords < 2 || parsePtr->numWords > 4) {
	return TCL_ERROR;
    }

    /*
     * Handle the message.
     */








|







2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;

    /*
     * General syntax: [error message ?errorInfo? ?errorCode?]
     */

    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
     * 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);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileForCmd --







|







2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
     * 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, (int)parsePtr->numWords-1, envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileForCmd --
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
 */

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
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    return CompileEachloopCmd(interp, parsePtr, cmdPtr, envPtr,
	    TCL_EACH_KEEP_NONE);
}








|







2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
 */

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 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
 */

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. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    return CompileEachloopCmd(interp, parsePtr, cmdPtr, envPtr,
	    TCL_EACH_COLLECT);
}

/*







|
|







2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
 */

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 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
    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;

    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;
    if ((numWords < 4) || (numWords%2 != 0)) {
	return TCL_ERROR;
    }

    /*
     * Bail out if the body requires substitutions in order to insure correct
     * behaviour. [Bug 219166]
     */

    for (i = 0, tokenPtr = parsePtr->tokenPtr; i < numWords-1; i++) {
	tokenPtr = TokenAfter(tokenPtr);
    }
    bodyTokenPtr = tokenPtr;







|
>











|





|







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
    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, 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 = (int)parsePtr->numWords;
    if ((numWords < 4) || (numWords%2 != 0)) {
	return TCL_ERROR;
    }

    /*
     * 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
     */

    TclNewObj(varListObj);
    for (i = 0, tokenPtr = parsePtr->tokenPtr;
	    i < numWords-1;
	    i++, tokenPtr = TokenAfter(tokenPtr)) {
	ForeachVarList *varListPtr;
	int 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) ||
		numVars == 0) {
	    code = TCL_ERROR;
	    goto done;
	}

	varListPtr = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes)
		+ numVars * sizeof(int));
	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_ListObjIndex(NULL, varListObj, j, &varNameObj);
	    bytes = TclGetStringFromObj(varNameObj, &length);
	    varIndex = LocalScalar(bytes, length, envPtr);
	    if (varIndex < 0) {
		code = TCL_ERROR;







|












|






|








|







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
     */

    TclNewObj(varListObj);
    for (i = 0, tokenPtr = parsePtr->tokenPtr;
	    i < numWords-1;
	    i++, tokenPtr = TokenAfter(tokenPtr)) {
	ForeachVarList *varListPtr;
	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 != TclListObjLength(NULL, varListObj, &numVars) ||
		numVars == 0) {
	    code = TCL_ERROR;
	    goto done;
	}

	varListPtr = (ForeachVarList *)Tcl_Alloc(offsetof(ForeachVarList, varIndexes)
		+ 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;
	    Tcl_Size length;


	    Tcl_ListObjIndex(NULL, varListObj, j, &varNameObj);
	    bytes = TclGetStringFromObj(varNameObj, &length);
	    varIndex = LocalScalar(bytes, length, envPtr);
	    if (varIndex < 0) {
		code = TCL_ERROR;
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
 *	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
DupForeachInfo(
    ClientData 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));
	dupListPtr->numVars = numVars;
	for (j = 0;  j < numVars;  j++) {
	    dupListPtr->varIndexes[j] =	srcListPtr->varIndexes[j];
	}
	dupPtr->varLists[i] = dupListPtr;
    }
    return dupPtr;







|

|

















|







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
 *	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 void *
DupForeachInfo(
    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(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
 *	ForeachInfo structure.
 *
 *----------------------------------------------------------------------
 */

static void
FreeForeachInfo(
    ClientData clientData)	/* The foreach command's compilation auxiliary
				 * data to free. */
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *listPtr;
    int numLists = infoPtr->numLists;
    int i;

    for (i = 0;  i < numLists;  i++) {
	listPtr = infoPtr->varLists[i];
	Tcl_Free(listPtr);
    }
    Tcl_Free(infoPtr);
}







|




|
<







3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026

3027
3028
3029
3030
3031
3032
3033
 *	ForeachInfo structure.
 *
 *----------------------------------------------------------------------
 */

static void
FreeForeachInfo(
    void *clientData)	/* The foreach command's compilation auxiliary
				 * data to free. */
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *listPtr;
    size_t i, numLists = infoPtr->numLists;


    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
PrintForeachInfo(
    ClientData clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *varsPtr;
    int 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, "], loop=%%v%u",
	    (unsigned) 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));
	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_AppendToObj(appendObj, "]", -1);
    }
}

static void
PrintNewForeachInfo(
    ClientData clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *varsPtr;
    int i, j;

    Tcl_AppendPrintfToObj(appendObj, "jumpOffset=%+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_AppendToObj(appendObj, "]", -1);
    }
}

static void
DisassembleForeachInfo(
    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;

    /*
     * Data stores.
     */

    TclNewObj(objPtr);







|


|



|







|
|

|
|




|
|





|
|







|


|



|

|











|
|







|


|



|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
PrintForeachInfo(
    void *clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(size_t))
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *varsPtr;
    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%" TCL_Z_MODIFIER "u",
		(infoPtr->firstValueTemp + i));
    }
    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%" 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%" TCL_Z_MODIFIER "u",
		    varsPtr->varIndexes[j]);
	}
	Tcl_AppendToObj(appendObj, "]", -1);
    }
}

static void
PrintNewForeachInfo(
    void *clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(size_t))
{
    ForeachInfo *infoPtr = (ForeachInfo *)clientData;
    ForeachVarList *varsPtr;
    Tcl_Size i, j;

    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%" TCL_Z_MODIFIER "u",
		    varsPtr->varIndexes[j]);
	}
	Tcl_AppendToObj(appendObj, "]", -1);
    }
}

static void
DisassembleForeachInfo(
    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;

    /*
     * Data stores.
     */

    TclNewObj(objPtr);
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
	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),







|


|



|







3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
	Tcl_ListObjAppendElement(NULL, objPtr, innerPtr);
    }
    Tcl_DictObjPut(NULL, dictObj, Tcl_NewStringObj("assign", -1), 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("jumpOffset", -1),
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
    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;

    /*
     * Don't handle any guaranteed-error cases.
     */

    if (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++) {
	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);
    for (; --i>=0 ;) {
	Tcl_DecrRefCount(objv[i]);
    }
    Tcl_Free(objv);
    Tcl_DecrRefCount(formatObj);
    if (tmpObj == NULL) {
	TclCompileSyntaxError(interp, envPtr);







|





|
















|
|














|







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
    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;
    Tcl_Size len;

    /*
     * Don't handle any guaranteed-error cases.
     */

    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(((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),
	    (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
	}
    }

    /*
     * Check if the number of things to concatenate will fit in a byte.
     */

    if (i+2 != 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







|







3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
	}
    }

    /*
     * Check if the number of things to concatenate will fit in a byte.
     */

    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
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
 *	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.
 *
 * Side effects:
 *	May add an entery into the table of compiled locals.
 *
 *----------------------------------------------------------------------
 */

int
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
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}};


    token[1].start = bytes;
    token[1].size = numBytes;
    return TclLocalScalarFromToken(token, envPtr);
}

/*







|


|




|













|





|
>
|
>







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
 *	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 TCL_INDEX_NONE.
 *
 * Side effects:
 *	May add an entry into the table of compiled locals.
 *
 *----------------------------------------------------------------------
 */

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;
}

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}
    };

    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
	    && (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++) {
	    if (*p == '(') {
		simpleVarName = 1;
		break;
	    }
	}
	if (simpleVarName) {
	    size_t remainingLen;







|
|







3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
	    && (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++) {
	    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
	/*
	 * 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) == ':')) {
		hasNsQualifiers = 1;
		break;
	    }
	}

	/*
	 * Look up the var name's index in the array of local vars in the proc







|







3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
	/*
	 * See whether name has any namespace separators (::'s).
	 */

	int hasNsQualifiers = 0;

	for (p = name, last = p + nameLen-1;  p < last;  p++) {
	    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
/*
 * 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.
 *
 * 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"







|
|
|
|







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 © 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
				 * 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;
    const char *word;
    int realCond = 1;		/* Set to 0 for static conditions:
				 * "if 0 {..}" */
    int boolVal;		/* Value of static condition. */
    int compileScripts = 1;

    /*







|
|







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, 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
     */

    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
	     * target (just after this jump) down three bytes.
	     */

	    unsigned char *ifFalsePc = envPtr->codeStart
		    + jumpFalseFixupArray.fixup[jumpIndex].codeOffset;
	    unsigned char opCode = *ifFalsePc;








|







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 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;

577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
 */

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
				 * compiled. */
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;
    Tcl_Obj *objPtr;
    const char *bytes;







|







577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
 */

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 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

    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.
     */

    /* 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);







|
|







615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630

    if (bytes[0] != ':' || bytes[1] != ':' || !TclMatchIsTrivial(bytes)) {
	goto notCompilable;
    }
    Tcl_DecrRefCount(objPtr);

    /*
     * 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
    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;

    if (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);

    /*
     * 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;
    }

    /*
     * 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);
    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++) {
	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);
	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,
	 * 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
	 * with a pre-adjustment of the end-N value.
	 * The root of this is that the commands [lrange] and [linsert]
	 * differ in their interpretation of the "end" index.
	 */

	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;
}

/*
 *----------------------------------------------------------------------
 *







|
|

|


<

<
<
<
<
<
|
|
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
|
|
|



<

<
>
|
<
<
<
<
|
<
<
<
|
<
>
|
<
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<







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_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;
    int i;

    if ((int)parsePtr->numWords < 3) {
	return TCL_ERROR;
    }







    /* Push list, insertion index onto the stack */
    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    CompileWord(envPtr, tokenPtr, interp, 1);











    tokenPtr = TokenAfter(tokenPtr);







    CompileWord(envPtr, tokenPtr, interp, 2);





    /* Push new elements to be inserted */
    for (i=3 ; i<(int)parsePtr->numWords ; i++) {
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);
    }



    /* First operand is count of arguments */
    TclEmitInstInt4(INST_LREPLACE4, parsePtr->numWords - 1, envPtr);




    /*



     * Second operand is bitmask

     *  TCL_LREPLACE4_END_IS_LAST - end refers to last element
     *  TCL_LREPLACE4_SINGLE_INDEX - second index is not present

     *     indicating this is a pure insert

     */
    TclEmitInt1(TCL_LREPLACE4_SINGLE_INDEX, 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
    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;
    int emptyPrefix=1, suffixStart = 0;

    if (parsePtr->numWords < 4) {
	return TCL_ERROR;
    }
    listTokenPtr = TokenAfter(parsePtr->tokenPtr);


    tokenPtr = TokenAfter(listTokenPtr);
    if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_START, TCL_INDEX_NONE,
	    &idx1) != TCL_OK) {
	return TCL_ERROR;
    }

    tokenPtr = TokenAfter(tokenPtr);
    if (TclGetIndexFromToken(tokenPtr, TCL_INDEX_NONE, TCL_INDEX_END,
	    &idx2) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * 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.
     */

    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);

    /*
     * Push all the replacement values next so any errors raised in
     * creating them get raised first.
     */
    if (parsePtr->numWords > 4) {
	/* Push the replacement arguments */
	tokenPtr = TokenAfter(tokenPtr);
	for (i=4 ; i<parsePtr->numWords ; i++) {
	    CompileWord(envPtr, tokenPtr, interp, i);
	    tokenPtr = TokenAfter(tokenPtr);
	}

	/* Make a list of them... */
	TclEmitInstInt4(	INST_LIST, i - 4,		envPtr);

	emptyPrefix = 0;
    }

    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.

	 */
	TclEmitInstInt4(	INST_LIST_RANGE_IMM, 0,		envPtr);
	TclEmitInt4(			(int)TCL_INDEX_END,		envPtr);
	return TCL_OK;
    }

    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;
}

/*
 *----------------------------------------------------------------------
 *







|
|
<




<

>
|
<
<
<
<
|

<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
|
<
<
|
<

<
|
<
|

<
<
|
<
<
|
<
|
<
<
|
>
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
    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;
    int i;


    if (parsePtr->numWords < 4) {
	return TCL_ERROR;
    }


    /* Push list, first, last onto the stack */
    tokenPtr = TokenAfter(parsePtr->tokenPtr);




    CompileWord(envPtr, tokenPtr, interp, 1);
    tokenPtr = TokenAfter(tokenPtr);




    CompileWord(envPtr, tokenPtr, interp, 2);










    tokenPtr = TokenAfter(tokenPtr);














    CompileWord(envPtr, tokenPtr, interp, 3);


    /* Push new elements to be inserted */


    for (i=4 ; i< (int)parsePtr->numWords ; i++) {

	tokenPtr = TokenAfter(tokenPtr);

	CompileWord(envPtr, tokenPtr, interp, i);

    }



    /* First operand is count of arguments */


    TclEmitInstInt4(INST_LREPLACE4, parsePtr->numWords - 1, envPtr);

    /*


     * Second operand is bitmask
     *  TCL_LREPLACE4_END_IS_LAST - end refers to last element
     */




    TclEmitInt1(TCL_LREPLACE4_END_IS_LAST, envPtr);


































    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
    int i;

    /*
     * Check argument count.
     */

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords < 3) {
	/*
	 * Fail at run time, not in compilation.
	 */

	return TCL_ERROR;
    }








|







1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
    int i;

    /*
     * Check argument count.
     */

    /* TODO: Consider support for compiling expanded args. */
    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
    PushVarNameWord(interp, varTokenPtr, envPtr, 0,
	    &localIndex, &isScalar, 1);

    /*
     * Push the "index" args and the new element value.
     */

    for (i=2 ; i<parsePtr->numWords ; ++i) {
	varTokenPtr = TokenAfter(varTokenPtr);
	CompileWord(envPtr, varTokenPtr, interp, i);
    }

    /*
     * Duplicate the variable name if it's been pushed.
     */







|







1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
    PushVarNameWord(interp, varTokenPtr, envPtr, 0,
	    &localIndex, &isScalar, 1);

    /*
     * Push the "index" args and the new element value.
     */

    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
	return TCL_ERROR;
    }

    /*
     * Only compile [namespace upvar ...]: needs an even number of args, >=4
     */

    numWords = parsePtr->numWords;
    if ((numWords % 2) || (numWords < 4)) {
	return TCL_ERROR;
    }

    /*
     * Push the namespace
     */







|







1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
	return TCL_ERROR;
    }

    /*
     * Only compile [namespace upvar ...]: needs an even number of args, >=4
     */

    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
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr, *opt;
    int idx;

    if (parsePtr->numWords < 2 || 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







|







1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr, *opt;
    int idx;

    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
    /*
     * 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) {
	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++) {
	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)) {
	    nocase = 1;
	} else {
	    /*
	     * Not an option we recognize.
	     */

	    return TCL_ERROR;
	}
    }

    if ((parsePtr->numWords - i) != 2) {
	/*
	 * We don't support capturing to variables.
	 */

	return TCL_ERROR;
    }








|














|














|










|







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
    /*
     * We are only interested in compiling simple regexp cases. Currently
     * supported compile cases are:
     *   regexp ?-nocase? ?--? staticString $var
     *   regexp ?-nocase? ?--? {^staticString$} $var
     */

    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 < (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)) {
	    nocase = 1;
	} else {
	    /*
	     * Not an option we recognize.
	     */

	    return TCL_ERROR;
	}
    }

    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
	    simple = 1;
	    PushLiteral(envPtr, Tcl_DStringValue(&ds),Tcl_DStringLength(&ds));
	    Tcl_DStringFree(&ds);
	}
    }

    if (!simple) {
	CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 2);
    }

    /*
     * Push the string arg.
     */

    varTokenPtr = TokenAfter(varTokenPtr);
    CompileWord(envPtr, varTokenPtr, interp, parsePtr->numWords - 1);

    if (simple) {
	if (exact && !nocase) {
	    TclEmitOpcode(	INST_STR_EQ,			envPtr);
	} else {
	    TclEmitInstInt1(	INST_STR_MATCH, nocase,		envPtr);
	}







|







|







2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
	    simple = 1;
	    PushLiteral(envPtr, Tcl_DStringValue(&ds),Tcl_DStringLength(&ds));
	    Tcl_DStringFree(&ds);
	}
    }

    if (!simple) {
	CompileWord(envPtr, varTokenPtr, interp, (int)parsePtr->numWords - 2);
    }

    /*
     * Push the string arg.
     */

    varTokenPtr = TokenAfter(varTokenPtr);
    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

    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;

    if (parsePtr->numWords < 5 || 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).
     */







|

|







2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125

    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;
    Tcl_Size len;

    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
     */

    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);
    TclEmitOpcode(	INST_STR_MAP,	envPtr);

  done:
    Tcl_DStringFree(&pattern);
    if (patternObj) {
	Tcl_DecrRefCount(patternObj);
    }







|







2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
     */

    result = TCL_OK;
    bytes = Tcl_DStringValue(&pattern) + 1;
    PushLiteral(envPtr,	bytes, len);
    bytes = TclGetStringFromObj(replacementObj, &len);
    PushLiteral(envPtr,	bytes, len);
    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
    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 numWords = parsePtr->numWords;
    int explicitResult = (0 == (numWords % 2));
    int numOptionWords = numWords - 1 - explicitResult;
    Tcl_Obj *returnOpts, **objv;
    Tcl_Token *wordTokenPtr = TokenAfter(parsePtr->tokenPtr);

    /*







|
>







2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
    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, 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
	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)) {
		enclosingCatch = 1;
		break;
	    }
	    index--;
	}
	if (!enclosingCatch) {
	    /*







|







2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
	int index = envPtr->exceptArrayNext - 1;
	int enclosingCatch = 0;

	while (index >= 0) {
	    ExceptionRange range = envPtr->exceptArrayPtr[index];

	    if ((range.type == CATCH_EXCEPTION_RANGE)
		    && (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

void
TclCompileSyntaxError(
    Tcl_Interp *interp,
    CompileEnv *envPtr)
{
    Tcl_Obj *msg = Tcl_GetObjResult(interp);
    size_t 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);







|







2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488

void
TclCompileSyntaxError(
    Tcl_Interp *interp,
    CompileEnv *envPtr)
{
    Tcl_Obj *msg = Tcl_GetObjResult(interp);
    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
    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_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.







|







2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
    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;
    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
	}

	/*
	 * Get the tail: immediately after the last '::'
	 */

	for (p = tailName + len -1; p > tailName; p--) {
	    if ((*p == ':') && (*(p - 1) == ':')) {
		p++;
		break;
	    }
	}
	if (!full && (p == tailName)) {
	    /*
	     * No :: in the last component.







|







2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
	}

	/*
	 * Get the tail: immediately after the last '::'
	 */

	for (p = tailName + len -1; p > tailName; p--) {
	    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
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int i;

    if (parsePtr->numWords > 255) {
	return TCL_ERROR;
    }

    for (i=0 ; i<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) {
	return TCL_ERROR;
    }

    for (i=0 ; i<parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    TclEmitInstInt1(	INST_TCLOO_NEXT_CLASS, i,	envPtr);
    return TCL_OK;
}








|



|



















|



|







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
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int i;

    if ((int)parsePtr->numWords > 255) {
	return TCL_ERROR;
    }

    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 ((int)parsePtr->numWords < 2 || (int)parsePtr->numWords > 255) {
	return TCL_ERROR;
    }

    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
/*
 * 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.
 *
 * 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"








|
|
|
|







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 © 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
			    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);
static void		IssueSwitchJumpTable(Tcl_Interp *interp,
			    CompileEnv *envPtr, int numWords,
				Tcl_Token **bodyToken, int *bodyLines,
				int **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,







|
|


|
|







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,
			    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, 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,
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280

    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 */

    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;
		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;
	const char *bytes = TclGetStringFromObj(folded, &len);

	PushLiteral(envPtr, bytes, len);
	Tcl_DecrRefCount(folded);
	folded = NULL;
	numArgs ++;
    }







|
















|

















|







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280

    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 */

    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) {
		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) {
	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
}

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
				 * 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
    };
    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;
    InstStringClassType strClassType;
    Tcl_Obj *isClass;

    if (parsePtr->numWords < 3 || parsePtr->numWords > 6) {
	return TCL_ERROR;
    }
    TclNewObj(isClass);







|







|
|
|
|
|



|
|
|
|
|
|
|







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
}

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 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
    };
    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
    } 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
     *	1. Character classes
     *	2. Booleans
     *	3. Integers
     *	4. Floats
     *	5. Lists
     */

    CompileWord(envPtr, tokenPtr, interp, parsePtr->numWords-1);

    switch ((enum isClassesEnum) 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:







|

|







569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
     *	1. Character classes
     *	2. Booleans
     *	3. Integers
     *	4. Floats
     *	5. Lists
     */

    CompileWord(envPtr, tokenPtr, interp, (int)parsePtr->numWords-1);

    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
	    } else {
		OP(	POP);
		PUSH(	"1");
	    }
	    FIXJUMP1(	over);
	    OP(		LNOT);
	    return TCL_OK;


	}
    break;

    case STR_IS_DOUBLE: {
	int satisfied, isEmpty;

	if (allowEmpty) {







>
>







676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
	    } 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
	    OP(		LE);
	    break;
	case STR_IS_INT:
	case STR_IS_ENTIER:
	    PUSH(	"3");
	    OP(		LE);
	    break;


	}
	FIXJUMP1(	end);
	return TCL_OK;
    case STR_IS_DICT:
	range = TclCreateExceptRange(CATCH_EXCEPTION_RANGE, envPtr);
	OP4(		BEGIN_CATCH4, range);
	ExceptionRangeStarts(envPtr, range);







>
>







743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
	    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
}

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
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;
	size_t length;
    int i, exactMatch = 0, nocase = 0;







|







785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
}

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 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
	 * 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);
	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
				 * 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;

    /*
     * We only handle the case:
     *
     *    string map {foo bar} $thing
     *
     * That is, a literal two-element list (doesn't need to be brace-quoted,







|















|







<
|







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
	 * something with backslashes). Just push the actual character (not
	 * byte) length.
	 */

	char buf[TCL_INTEGER_SPACE];
	size_t len = Tcl_GetCharLength(objPtr);

	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 definition of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *mapTokenPtr, *stringTokenPtr;
    Tcl_Obj *mapObj, **objv;
    const char *bytes;

    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
    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) {
	Tcl_DecrRefCount(mapObj);
	return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
    } else if (len != 2) {
	Tcl_DecrRefCount(mapObj);
	return TclCompileBasic2ArgCmd(interp, parsePtr, cmdPtr, envPtr);
    }








|







936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
    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 (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
    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) {
	return TCL_ERROR;
    }

    /* Bytecode to compute/push string argument being replaced */
    valueTokenPtr = TokenAfter(parsePtr->tokenPtr);
    CompileWord(envPtr, valueTokenPtr, interp, 1);








|







1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds the resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr, *valueTokenPtr;
    int first, last;

    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
}

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
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;

    if (parsePtr->numWords != 2) {







|







1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
}

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 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
}

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
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;

    if (parsePtr->numWords != 2) {







|







1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
}

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 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
}

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
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;

    if (parsePtr->numWords != 2) {







|







1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
}

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 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
    return TCL_OK;
}

void
TclSubstCompile(
    Tcl_Interp *interp,
    const char *bytes,
    size_t numBytes,
    int flags,
    int line,
    CompileEnv *envPtr)
{
    Tcl_Token *endTokenPtr, *tokenPtr;
    int breakOffset = 0, count = 0, bline = line;

    Tcl_Parse parse;
    Tcl_InterpState state = NULL;

    TclSubstParse(interp, bytes, numBytes, flags, &parse, &state);
    if (state != NULL) {
	Tcl_ResetResult(interp);
    }







|

|



|
>







1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
    return TCL_OK;
}

void
TclSubstCompile(
    Tcl_Interp *interp,
    const char *bytes,
    Tcl_Size numBytes,
    int flags,
    Tcl_Size line,
    CompileEnv *envPtr)
{
    Tcl_Token *endTokenPtr, *tokenPtr;
    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
    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;
	int literal, catchRange, breakJump;
	char buf[4] = "";
	JumpFixup startFixup, okFixup, returnFixup, breakFixup;
	JumpFixup continueFixup, otherFixup, endFixup;

	switch (tokenPtr->type) {
	case TCL_TOKEN_TEXT:







|







1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
    if (tokenPtr->type != TCL_TOKEN_TEXT && tokenPtr->type != TCL_TOKEN_BS) {
	PUSH("");
	count++;
    }

    for (endTokenPtr = tokenPtr + parse.numTokens;
	    tokenPtr < endTokenPtr; tokenPtr = TokenAfter(tokenPtr)) {
	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
	     * 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;
		int foundCommand = 0;

		for (i=2 ; i<=tokenPtr->numComponents ; i++) {
		    if (tokenPtr[i].type == TCL_TOKEN_COMMAND) {
			foundCommand = 1;
			break;
		    }







|







1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
	     * 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) {
		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

    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
				 * items. */
    int **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;

    /*
     * Only handle the following versions:
     *   switch         ?--? word {pattern body ...}
     *   switch -exact  ?--? word {pattern body ...}
     *   switch -glob   ?--? word {pattern body ...}
     *   switch -regexp ?--? word {pattern body ...}







|

|




|







1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813

    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. */
    Tcl_Size *bodyLines;	/* Array of line numbers for body list
				 * items. */
    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;
    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
     * 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,
				 * 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);

	bline = mapPtr->loc[eclIndex].line[valueIndex+1];
	numWords = 0;

	while (numBytes > 0) {
	    const char *prevBytes = bytes;
	    int literal;







|
|

















|
|







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
     * 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;
	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 = (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
	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);
	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.
	     */







|
|







2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
	return TCL_ERROR;
    } else {
	/*
	 * Multi-word definition of patterns & actions.
	 */

	bodyToken = (Tcl_Token **)Tcl_Alloc(sizeof(Tcl_Token *) * 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

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
				 * 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
				 * items. */
    int **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. */







|



|

|







2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128

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. */
    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. */
    Tcl_Size *bodyLines,		/* Array of line numbers for body list
				 * items. */
    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
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
				 * items. */
    int **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
     * 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);







|

|











|







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
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. */
    Tcl_Size *bodyLines,		/* Array of line numbers for body list
				 * items. */
    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 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
		    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_DStringFree(&buffer);
	} else {
	    /*
	     * This is a default clause, so patch up the fallthrough from the
	     * INST_JUMP_TABLE instruction to here.
	     */







|







2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
		    Tcl_DStringValue(&buffer), &isNew);
	    if (isNew) {
		/*
		 * First time we've encountered this match clause, so it must
		 * point to here.
		 */

		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
 *	FreeJumptableInfo: releases memory
 *	PrintJumptableInfo: none
 *	DisassembleJumptableInfo: none
 *
 *----------------------------------------------------------------------
 */

static ClientData
DupJumptableInfo(
    ClientData 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) {
	newHPtr = Tcl_CreateHashEntry(&newJtPtr->hashTable,
		Tcl_GetHashKey(&jtPtr->hashTable, hPtr), &isNew);
	Tcl_SetHashValue(newHPtr, Tcl_GetHashValue(hPtr));
    }
    return newJtPtr;
}

static void
FreeJumptableInfo(
    ClientData clientData)
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;

    Tcl_DeleteHashTable(&jtPtr->hashTable);
    Tcl_Free(jtPtr);
}

static void
PrintJumptableInfo(
    ClientData clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    unsigned int pcOffset)
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    const char *keyPtr;
    int 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",
		keyPtr, pcOffset + offset);
    }
}

static void
DisassembleJumptableInfo(
    ClientData clientData,
    Tcl_Obj *dictObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(unsigned int))
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;
    Tcl_Obj *mapping;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    const char *keyPtr;
    size_t offset;







|

|









|









|









|


|





|












|






|


|







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
 *	FreeJumptableInfo: releases memory
 *	PrintJumptableInfo: none
 *	DisassembleJumptableInfo: none
 *
 *----------------------------------------------------------------------
 */

static void *
DupJumptableInfo(
    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);
    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(
    void *clientData)
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;

    Tcl_DeleteHashTable(&jtPtr->hashTable);
    Tcl_Free(jtPtr);
}

static void
PrintJumptableInfo(
    void *clientData,
    Tcl_Obj *appendObj,
    TCL_UNUSED(ByteCode *),
    size_t pcOffset)
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    const char *keyPtr;
    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 %" TCL_Z_MODIFIER "u",
		keyPtr, pcOffset + offset);
    }
}

static void
DisassembleJumptableInfo(
    void *clientData,
    Tcl_Obj *dictObj,
    TCL_UNUSED(ByteCode *),
    TCL_UNUSED(size_t))
{
    JumptableInfo *jtPtr = (JumptableInfo *)clientData;
    Tcl_Obj *mapping;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    const char *keyPtr;
    size_t offset;
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
    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
	    || 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++) {
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);
    }
    TclEmitInstInt1(	INST_TAILCALL, parsePtr->numWords,	envPtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileThrowCmd --







|







|



|







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
    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
	    || 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<(int)parsePtr->numWords ; i++) {
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, i);
    }
    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
    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;


    if (numWords != 3) {
	return TCL_ERROR;
    }
    codeToken = TokenAfter(parsePtr->tokenPtr);
    msgToken = TokenAfter(codeToken);








|
>







2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
    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;
    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
    if (!codeKnown) {
	CompileWord(envPtr, codeToken, interp, 1);
	PUSH(			"-errorcode");
    }
    CompileWord(envPtr, msgToken, interp, 2);

    codeIsList = codeKnown && (TCL_OK ==
	    Tcl_ListObjLength(interp, objPtr, &len));
    codeIsValid = codeIsList && (len != 0);

    if (codeIsValid) {
	Tcl_Obj *errPtr, *dictPtr;

	TclNewLiteralStringObj(errPtr, "-errorcode");
	TclNewObj(dictPtr);







|







2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
    if (!codeKnown) {
	CompileWord(envPtr, codeToken, interp, 1);
	PUSH(			"-errorcode");
    }
    CompileWord(envPtr, msgToken, interp, 2);

    codeIsList = codeKnown && (TCL_OK ==
	    TclListObjLength(interp, objPtr, &len));
    codeIsValid = codeIsList && (len != 0);

    if (codeIsValid) {
	Tcl_Obj *errPtr, *dictPtr;

	TclNewLiteralStringObj(errPtr, "-errorcode");
	TclNewObj(dictPtr);
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
	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;

	    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
			|| (objc == 0)) {
		    TclDecrRefCount(tmpObj);
		    goto failedToCompile;
		}
		Tcl_ListObjReplace(NULL, tmpObj, 0, 0, 0, NULL);
		matchClauses[i] = tmpObj;
	    } else if (tokenPtr[1].size == 2







|















|







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
	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;
	    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)
			|| 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
	    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
		    || (objc > 2)) {
		TclDecrRefCount(tmpObj);
		goto failedToCompile;
	    }
	    if (objc > 0) {
		size_t 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;
		const char *varname = TclGetStringFromObj(objv[1], &len);

		optionVarIndices[i] = LocalScalar(varname, len, envPtr);
		if (optionVarIndices[i] < 0) {
		    TclDecrRefCount(tmpObj);
		    goto failedToCompile;
		}







|





|











|







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
	    tokenPtr = TokenAfter(tokenPtr);
	    TclNewObj(tmpObj);
	    Tcl_IncrRefCount(tmpObj);
	    if (!TclWordKnownAtCompileTime(tokenPtr, tmpObj)) {
		TclDecrRefCount(tmpObj);
		goto failedToCompile;
	    }
	    if (TclListObjGetElements(NULL, tmpObj, &objc, &objv) != TCL_OK
		    || (objc > 2)) {
		TclDecrRefCount(tmpObj);
		goto failedToCompile;
	    }
	    if (objc > 0) {
		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) {
		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
	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);



    } else {
	goto failedToCompile;
    }

    /*
     * Issue the bytecode.
     */







>
>
>







2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
	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
    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 *addrsToFix, *forwardsToFix, notCodeJumpSource, notECJumpSource;
    int *noError;
    char buf[TCL_INTEGER_SPACE];

    resultVar = AnonymousLocal(envPtr);
    optionsVar = AnonymousLocal(envPtr);
    if (resultVar < 0 || optionsVar < 0) {







|
|







3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
    Tcl_Obj **matchClauses,
    int *resultVars,
    int *optionVars,
    Tcl_Token **handlerTokens)
{
    DefineLineInformation;	/* TIP #280 */
    int range, resultVar, optionsVar;
    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

    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]);
	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);

	    /*
	     * Match the errorcode according to try/trap rules.
	     */

	    LOAD(			optionsVar);
	    PUSH(			"-errorcode");







|






|







3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137

    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;
	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;
	    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
    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 trapZero = 0, afterBody = 0, finalOK, finalError, noFinalError;
    int *addrsToFix, *forwardsToFix, notCodeJumpSource, notECJumpSource;
    char buf[TCL_INTEGER_SPACE];
    size_t slen;

    resultVar = AnonymousLocal(envPtr);
    optionsVar = AnonymousLocal(envPtr);
    if (resultVar < 0 || optionsVar < 0) {
	return TCL_ERROR;
    }








|



|







3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
    Tcl_Obj **matchClauses,
    int *resultVars,
    int *optionVars,
    Tcl_Token **handlerTokens,
    Tcl_Token *finallyToken)	/* Not NULL */
{
    DefineLineInformation;	/* TIP #280 */
    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];
    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
    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]);
	OP(				DUP);
	PushLiteral(envPtr, buf, strlen(buf));
	OP(				EQ);
	JUMP4(				JUMP_FALSE, notCodeJumpSource);
	if (matchClauses[i]) {
	    Tcl_ListObjLength(NULL, matchClauses[i], &len);

	    /*
	     * Match the errorcode according to try/trap rules.
	     */

	    LOAD(			optionsVar);
	    PUSH(			"-errorcode");







|





|







3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
    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;

	snprintf(buf, sizeof(buf), "%d", matchCodes[i]);
	OP(				DUP);
	PushLiteral(envPtr, buf, strlen(buf));
	OP(				EQ);
	JUMP4(				JUMP_FALSE, notCodeJumpSource);
	if (matchClauses[i]) {
	    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

    /*
     * 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++) {
	Tcl_Obj *leadingWord;

	TclNewObj(leadingWord);
	varTokenPtr = TokenAfter(varTokenPtr);
	if (!TclWordKnownAtCompileTime(varTokenPtr, leadingWord)) {
	    TclDecrRefCount(leadingWord);








|







3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647

    /*
     * 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<(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
		    continue;
		}
	    }
	    return TCL_ERROR;
	}
	if (varCount == 0) {
	    const char *bytes;
	    size_t 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++;







|







3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
		    continue;
		}
	    }
	    return TCL_ERROR;
	}
	if (varCount == 0) {
	    const char *bytes;
	    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
     * 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++) {
	/*
	 * 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.
	 */







|







3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
     * 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<(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
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
    int i;

    if (parsePtr->numWords < 2) {
	return TCL_ERROR;
    }

    OP(		NS_CURRENT);
    for (i = 1 ; i < parsePtr->numWords ; i++) {
	CompileWord(envPtr, tokenPtr, interp, i);
	tokenPtr = TokenAfter(tokenPtr);
    }
    OP4(	LIST, i);
    OP(		YIELD_TO_INVOKE);
    return TCL_OK;
}







|




|







3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = TokenAfter(parsePtr->tokenPtr);
    int i;

    if ((int)parsePtr->numWords < 2) {
	return TCL_ERROR;
    }

    OP(		NS_CURRENT);
    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
    Tcl_Parse *parsePtr,
    const char *identity,
    int instruction,
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int 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.
	 */

	OP4(	REVERSE, words-1);
    }
    while (--words > 1) {
	TclEmitOpcode(instruction, envPtr);
    }







|













|







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
    Tcl_Parse *parsePtr,
    const char *identity,
    int instruction,
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    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
	 * 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
    int instruction,
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;

    /* TODO: Consider support for compiling expanded args. */
    if (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;

	tokenPtr = TokenAfter(parsePtr->tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, 1);
	tokenPtr = TokenAfter(tokenPtr);
	CompileWord(envPtr, tokenPtr, interp, 2);
	STORE(tmpIndex);
	TclEmitOpcode(instruction, envPtr);







|















|







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
    int instruction,
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr;

    /* TODO: Consider support for compiling expanded args. */
    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);
	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
    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int words;

    /*
     * This one has its own implementation because the ** operator is the only
     * one with right associativity.
     */

    for (words=1 ; words<parsePtr->numWords ; words++) {







|







4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    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
    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    int words;

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords == 1) {
	/*
	 * Fallback to direct eval to report syntax error.
	 */








|







4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)
{
    DefineLineInformation;	/* TIP #280 */
    Tcl_Token *tokenPtr = parsePtr->tokenPtr;
    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
    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.
     */

    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;

    /* TODO: Consider support for compiling expanded args. */
    if (parsePtr->numWords == 1) {
	/*
	 * Fallback to direct eval to report syntax error.
	 */








|



















|







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
    if (words == 3) {
	TclEmitOpcode(INST_SUB, envPtr);
	return TCL_OK;
    }

    /*
     * Reverse order of arguments to get precise agreement with [expr] in
     * 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;
    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
    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.
     */

    TclEmitInstInt4(INST_REVERSE, words-1, envPtr);
    while (--words > 1) {
	TclEmitInstInt4(INST_REVERSE, 2, envPtr);
	TclEmitOpcode(INST_DIV, envPtr);
    }







|







4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
    if (words <= 3) {
	TclEmitOpcode(INST_DIV, envPtr);
	return TCL_OK;
    }

    /*
     * Reverse order of arguments to get precise agreement with [expr] in
     * 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
 *
 * 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.
 *
 * 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:
 */







|







92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
 *
 * 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 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:
 */
153
154
155
156
157
158
159
160
161
162
163
164
165
166


167
168
169
170
171
172
173

/* Uncategorized lexemes */

#define PLUS		1	/* Ambiguous. Resolves to UNARY_PLUS or
				 * BINARY_PLUS according to context. */
#define MINUS		2	/* Ambiguous. Resolves to UNARY_MINUS or
				 * BINARY_MINUS according to context. */
#define BAREWORD	3	/* Ambigous. Resolves to BOOLEAN or to
				 * FUNCTION or a parse error according to
				 * context and value. */
#define INCOMPLETE	4	/* A parse error. Used only when the single
				 * "=" is encountered.  */
#define INVALID		5	/* A parse error. Used when any punctuation
				 * appears that's not a supported operator. */



/* Leaf lexemes */

#define NUMBER		(LEAF | 1)
				/* For literal numbers */
#define SCRIPT		(LEAF | 2)
				/* Script substitution; [foo] */







|






>
>







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

/* Uncategorized lexemes */

#define PLUS		1	/* Ambiguous. Resolves to UNARY_PLUS or
				 * BINARY_PLUS according to context. */
#define MINUS		2	/* Ambiguous. Resolves to UNARY_MINUS or
				 * BINARY_MINUS according to context. */
#define BAREWORD	3	/* Ambiguous. Resolves to BOOLEAN or to
				 * FUNCTION or a parse error according to
				 * context and value. */
#define INCOMPLETE	4	/* A parse error. Used only when the single
				 * "=" is encountered.  */
#define INVALID		5	/* A parse error. Used when any punctuation
				 * appears that's not a supported operator. */
#define COMMENT		6	/* Comment. Lasts to end of line or end of
				 * expression, whichever comes first. */

/* Leaf lexemes */

#define NUMBER		(LEAF | 1)
				/* For literal numbers */
#define SCRIPT		(LEAF | 2)
				/* Script substitution; [foo] */
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
	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		/* # */,
	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 */







|







460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
	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		/* " */,	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
 * 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,
			    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_Obj *litList, Tcl_Obj *funcList,
			    Tcl_Parse *parsePtr, int parseOnly);
static size_t		ParseLexeme(const char *start, size_t numBytes,
			    unsigned char *lexemePtr, Tcl_Obj **literalPtr);

/*
 *----------------------------------------------------------------------
 *
 * ParseExpr --
 *







|





|


|







507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
 * 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, 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,
			    Tcl_Size numBytes, OpNode **opTreePtr,
			    Tcl_Obj *litList, Tcl_Obj *funcList,
			    Tcl_Parse *parsePtr, int parseOnly);
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
 *----------------------------------------------------------------------
 */

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. */
    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
				 * 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
				 * 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







|

















|




|







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
 *----------------------------------------------------------------------
 */

static int
ParseExpr(
    Tcl_Interp *interp,		/* Used for error reporting. */
    const char *start,		/* Start of source string to parse. */
    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 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. */
    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
				 * 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
				 * 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);








|







621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
				 * 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 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
	 */

	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));
	      }
	    } while ((newPtr == NULL)
		    && ((size -= (size - nodesUsed) / 2) > nodesUsed));
	    if (newPtr == NULL) {
		TclNewLiteralStringObj(msg,
			"not enough memory to parse expression");
		errCode = "NOMEM";
		goto error;







|
>
|
|







672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
	 */

	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));
		}
	    } 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
	 * Use context to categorize the lexemes that are ambiguous.
	 */

	if ((NODE_TYPE & lexeme) == 0) {
	    int b;

	    switch (lexeme) {




	    case INVALID:
		msg = Tcl_ObjPrintf("invalid character \"%.*s\"",
			(int)scanned, start);
		errCode = "BADCHAR";
		goto error;
	    case INCOMPLETE:
		msg = Tcl_ObjPrintf("incomplete operator \"%.*s\"",







>
>
>
>







707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
	 * 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\"",
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
		     * 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;
		} else {


























		    Tcl_DecrRefCount(literal);
		    msg = Tcl_ObjPrintf("invalid bareword \"%.*s%s\"",
			    (scanned < limit) ? (int)scanned : (int)limit - 3, start,
			    (scanned < limit) ? "" : "...");
		    post = Tcl_ObjPrintf(
			    "should be \"$%.*s%s\" or \"{%.*s%s}\"",
			    (scanned < limit) ? (int)scanned : (int)limit - 3,
			    start, (scanned < limit) ? "" : "...",
			    (scanned < limit) ? (int)scanned : (int)limit - 3,
			    start, (scanned < limit) ? "" : "...");
		    Tcl_AppendPrintfToObj(post, " or \"%.*s%s(...)\" or ...",
			    (scanned < limit) ? (int)scanned : (int)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);








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|



|

|


|







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
		     * 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;
		} 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\"",
			    (int)((scanned < limit) ? scanned : limit - 3), start,
			    (scanned < limit) ? "" : "...");
		    post = Tcl_ObjPrintf(
			    "should be \"$%.*s%s\" or \"{%.*s%s}\"",
			    (int) ((scanned < limit) ? scanned : limit - 3),
			    start, (scanned < limit) ? "" : "...",
			    (int) ((scanned < limit) ? scanned : limit - 3),
			    start, (scanned < limit) ? "" : "...");
		    Tcl_AppendPrintfToObj(post, " or \"%.*s%s(...)\" or ...",
			    (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);

1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
	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);
	}
    }

    return TCL_ERROR;
}

/*







|







1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
	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, (void *)NULL);
	}
    }

    return TCL_ERROR;
}

/*
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
 *
 *----------------------------------------------------------------------
 */

static void
ConvertTreeToTokens(
    const char *start,
    size_t numBytes,
    OpNode *nodes,
    Tcl_Token *tokenPtr,
    Tcl_Parse *parsePtr)
{
    int subExprTokenIdx = 0;
    OpNode *nodePtr = nodes;
    int next = nodePtr->right;







|







1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
 *
 *----------------------------------------------------------------------
 */

static void
ConvertTreeToTokens(
    const char *start,
    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
	    /*
	     * Here we scan from the string the operator corresponding to
	     * nodePtr->lexeme.
	     */

	    scanned = ParseLexeme(start, numBytes, &lexeme, NULL);

	    switch(nodePtr->lexeme) {
	    case OPEN_PAREN:
	    case COMMA:
	    case COLON:

		/*
		 * No tokens for these lexemes -> nothing to do.
		 */







|







1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
	    /*
	     * Here we scan from the string the operator corresponding to
	     * nodePtr->lexeme.
	     */

	    scanned = ParseLexeme(start, numBytes, &lexeme, NULL);

	    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
		 * 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;

		/*
		 * 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.
		 */








|







1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
		 * 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 =
			((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
 *----------------------------------------------------------------------
 */

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
				 * 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) {
	numBytes = (start ? strlen(start) : 0);
    }

    code = ParseExpr(interp, start, numBytes, &opTree, litList, funcList,
	    exprParsePtr, 1 /* parseOnly */);
    Tcl_DecrRefCount(funcList);
    Tcl_DecrRefCount(litList);







|















|







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
 *----------------------------------------------------------------------
 */

int
Tcl_ParseExpr(
    Tcl_Interp *interp,		/* Used for error reporting. */
    const char *start,		/* Start of source string to parse. */
    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 < 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
 *	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.
 *
 *----------------------------------------------------------------------
 */

static size_t
ParseLexeme(
    const char *start,		/* Start of lexeme to parse. */
    size_t 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. */
{
    const char *end;
    Tcl_UniChar ch = 0;
    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 '*':
	if ((numBytes > 1) && (start[1] == '*')) {
	    *lexemePtr = EXPON;
	    return 2;
	}
	*lexemePtr = MULT;
	return 1;







|




|


|






|













>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	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 written to *lexemePtr.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Size
ParseLexeme(
    const char *start,		/* Start of lexeme to parse. */
    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. */
{
    const char *end;
    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

    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) {

		*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)) {
		const char *p = start;

		while (p < end) {
		    if (!TclIsBareword(*p++)) {
			/*
			 * The number has non-bareword characters, so we
			 * must treat it as a number.







<


>















|







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

    TclNewObj(literal);
    if (TclParseNumber(NULL, literal, NULL, start, numBytes, &end,
	    TCL_PARSE_NO_WHITESPACE) == TCL_OK) {
	if (end < start + numBytes && !TclIsBareword(*end)) {

	number:

	    *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 (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
    /*
     * 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;
	if (Tcl_UtfCharComplete(start, numBytes)) {
	    scanned = TclUtfToUniChar(start, &ch);
	} else {
	    char utfBytes[4];

	    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));
	*literalPtr = literal;
    } else {
	Tcl_DecrRefCount(literal);
    }
    return (end-start);
}








|



|
















|







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
    /*
     * 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 == '_') {
	Tcl_Size scanned;
	if (Tcl_UtfCharComplete(start, numBytes)) {
	    scanned = TclUtfToUniChar(start, &ch);
	} else {
	    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, 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
 *----------------------------------------------------------------------
 */

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. */
    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_Obj *const *litObjv;
	Tcl_Obj **funcObjv;

	/* TIP #280 : Track Lines within the expression */
	TclAdvanceLines(&envPtr->line, script,
		script + TclParseAllWhiteSpace(script, numBytes));








|




















|







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
 *----------------------------------------------------------------------
 */

void
TclCompileExpr(
    Tcl_Interp *interp,		/* Used for error reporting. */
    const char *script,		/* The source script to compile. */
    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.
	 */

	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
	} else if (nodePtr->mark == MARK_RIGHT) {
	    next = nodePtr->right;

	    switch (nodePtr->lexeme) {
	    case FUNCTION: {
		Tcl_DString cmdName;
		const char *p;
		size_t length;

		Tcl_DStringInit(&cmdName);
		TclDStringAppendLiteral(&cmdName, "tcl::mathfunc::");
		p = TclGetStringFromObj(*funcObjv, &length);
		funcObjv++;
		Tcl_DStringAppend(&cmdName, p, length);
		TclEmitPush(TclRegisterLiteral(envPtr,







|







2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
	} else if (nodePtr->mark == MARK_RIGHT) {
	    next = nodePtr->right;

	    switch (nodePtr->lexeme) {
	    case FUNCTION: {
		Tcl_DString cmdName;
		const char *p;
		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
	    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;
		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.
		     */

		    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
		 * registration that would enable sharing, and use the routine
		 * that preserves intreps.
		 */

		TclEmitPush(TclAddLiteralObj(envPtr, literal, NULL), envPtr);
	    }
	    (*litObjvPtr)++;
	    break;
	}







|















|












|

|







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
	    numWords = 1;	/* No arguments, so just the command */
	    break;
	case OT_LITERAL: {
	    Tcl_Obj *const *litObjv = *litObjvPtr;
	    Tcl_Obj *literal = *litObjv;

	    if (optimize) {
		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 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 internalrep. In this case, skip literal
		 * registration that would enable sharing, and use the routine
		 * 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
		    /*
		     * 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;
			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.
			     */

			    tableValue->typePtr = objPtr->typePtr;
			    tableValue->internalRep = objPtr->internalRep;
			    objPtr->typePtr = NULL;
			}
		    } else {







|








|







2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
		    /*
		     * 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;
			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 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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclSingleOpCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
    unsigned char lexeme;
    OpNode nodes[2];







|







2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclSingleOpCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclSortingOpCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int code = TCL_OK;

    if (objc < 3) {







|







2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclSortingOpCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclVariadicOpCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;
    unsigned char lexeme;
    int code;







|







2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclVariadicOpCmd(
    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
	    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);
	    } else {
		TclNewIntObj(litObjv[0], occdPtr->i.identity);
	    }
	    Tcl_IncrRefCount(litObjv[0]);
	    litObjv[1] = objv[1];
	    nodes[0].lexeme = START;
	    nodes[0].mark = MARK_RIGHT;







|







2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
	    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) {
		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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclNoIdentOpCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    TclOpCmdClientData *occdPtr = (TclOpCmdClientData *)clientData;

    if (objc < 2) {







|







2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclNoIdentOpCmd(
    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
/*
 * 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.
 *
 * 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"







|
|







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 © 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"
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
	/* 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) */















    {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);
static void		EnterCmdStartData(CompileEnv *envPtr,
			    int cmdNumber, int srcOffset, int 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,
			    Tcl_Token *tokenPtr, const char *cmd,
			    int numWords, int line, int *clNext, int **lines,

			    CompileEnv *envPtr);
static void		ReleaseCmdWordData(ExtCmdLoc *eclPtr);

/*

 * The structure below defines the bytecode Tcl object type by means of
 * procedures that can be invoked by generic object code.
 */

const Tcl_ObjType tclByteCodeType = {
    "bytecode",			/* name */
    FreeByteCodeInternalRep,	/* freeIntRepProc */
    DupByteCodeInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetByteCodeFromAny		/* setFromAnyProc */

};

/*
 * The structure below defines a bytecode Tcl object type to hold the
 * compiled bytecode for the [subst]itution of Tcl values.
 */

static const Tcl_ObjType substCodeType = {
    "substcode",		/* name */
    FreeSubstCodeInternalRep,	/* freeIntRepProc */
    DupByteCodeInternalRep,	/* dupIntRepProc - shared with bytecode */
    NULL,			/* updateStringProc */
    NULL,			/* setFromAnyProc */

};
#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
 *	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
 *	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. */
{
    Interp *iPtr = (Interp *) interp;
    CompileEnv compEnv;		/* Compilation environment structure allocated
				 * in frame. */
    size_t 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
     * 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);

    /*

     * Now we check if we have data about invisible continuation lines for the
     * 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(),
     * found in this file. The "lineCLPtr" hashtable is managed in the file
     * "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.
     */

    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 (Tcl_GetParent(interp) == NULL &&
	    !Tcl_LimitTypeEnabled(interp, TCL_LIMIT_COMMANDS|TCL_LIMIT_TIME)
	    && IsCompactibleCompileEnv(&compEnv)) {
	TclFreeCompileEnv(&compEnv);
	iPtr->compiledProcPtr = procPtr;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
















|

|
















|

|
>




>
|
<







|
>



|
|








>
















<
|
|
|



|
|
<
















|




|


















|








>
|
<



|
|
<
|










|







|
|
|







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
	/* 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,
			    Tcl_Size cmdNumber, Tcl_Size numSrcBytes, Tcl_Size numCodeBytes);
static void		EnterCmdStartData(CompileEnv *envPtr,
			    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, Tcl_Size srcOffset,
			    Tcl_Token *tokenPtr, const char *cmd,
			    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
 * bytecode type.

 */

const Tcl_ObjType tclByteCodeType = {
    "bytecode",			/* name */
    FreeByteCodeInternalRep,	/* freeIntRepProc */
    DupByteCodeInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetByteCodeFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 * 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

 *	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:
 *	A standard Tcl object result. If an error occurs during compilation, an
 *	error message is left in the interpreter's 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. */
    void *clientData)	/* Hook procedure private data. */
{
    Interp *iPtr = (Interp *) interp;
    CompileEnv compEnv;		/* Compilation environment structure allocated
				 * in frame. */
    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
     * 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
     * continuation lines for the script.

     *
     * 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 set a lock
     * on it, which is released in TclFreeCompileEnv().  The "lineCLPtr"

     * hashtable tclObj.c.
     */

    clLocPtr = TclContinuationsGet(objPtr);
    if (clLocPtr) {
	compEnv.clNext = &clLocPtr->loc[0];
    }

    TclCompileScript(interp, stringPtr, length, &compEnv);

    /*
     * Compilation succeeded. Add a "done" instruction at the end.
     */

    TclEmitOpcode(INST_DONE, &compEnv);

    /*
     * Check for optimizations!
     *
     * 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
     */

    if (iPtr->optimizer) {
	(iPtr->optimizer)(&compEnv);
    }

    /*
     * Invoke the compilation hook procedure if one exists.
     */

    if (hookProc) {
	result = hookProc(interp, &compEnv, clientData);
    }













    /*
     * Change the object into a ByteCode object. Ownership of the literal
     * objects and aux data items is given to the ByteCode object.
     */

#ifdef TCL_COMPILE_DEBUG
    TclVerifyLocalLiteralTable(&compEnv);
#endif /*TCL_COMPILE_DEBUG*/

    if (result == TCL_OK) {







|





>
>
>
>
>
>
>
>
>
>
>
>



|







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
     */

    if (iPtr->optimizer) {
	(iPtr->optimizer)(&compEnv);
    }

    /*
     * 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 passes to the ByteCode object.
     */

#ifdef TCL_COMPILE_DEBUG
    TclVerifyLocalLiteralTable(&compEnv);
#endif /*TCL_COMPILE_DEBUG*/

    if (result == TCL_OK) {
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
 * 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.
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

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. */
{
    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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *







|
|
|


|











|













|
|
|







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
 * 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:
 *	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
 *	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 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, 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
 *	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.
 *
 *----------------------------------------------------------------------
 */

static void
FreeByteCodeInternalRep(
    Tcl_Obj *objPtr)	/* Object whose internal rep to free. */
{
    ByteCode *codePtr;

    ByteCodeGetIntRep(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.
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

void
TclPreserveByteCode(
    ByteCode *codePtr)







|
|
|










|










|
|
|





|
|







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
 *	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 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;

    ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * TclReleaseByteCode --
 *
 *	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 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
	ByteCodeStats *statsPtr;
	Tcl_Time destroyTime;
	int lifetimeSec, lifetimeMicroSec, log2;

	statsPtr = &iPtr->stats;

	statsPtr->numByteCodesFreed++;
	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);







|







1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
	ByteCodeStats *statsPtr;
	Tcl_Time destroyTime;
	int lifetimeSec, lifetimeMicroSec, log2;

	statsPtr = &iPtr->stats;

	statsPtr->numByteCodesFreed++;
	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
	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
     * 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).
     * Also, as the interp deletion will remove the global literal table
     * anyway, we 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++) {







|
|








|
|
|

|







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
	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 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 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, 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
	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.
     *
     * See also tclBasic.c, DeleteInterpProc
     */

    if (iPtr) {
	Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr,
		(char *) codePtr);







|
|
|







1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
	if (auxDataPtr->type->freeProc != NULL) {
	    auxDataPtr->type->freeProc(auxDataPtr->clientData);
	}
	auxDataPtr++;
    }

    /*
     * 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);
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
}

/*
 * ---------------------------------------------------------------------
 *
 * IsCompactibleCompileEnv --
 *
 *	Checks to see if we may apply some basic compaction optimizations 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
     * 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.
     */

    for (pc = envPtr->codeStart ; pc < envPtr->codeNext ; pc += size) {
	switch (*pc) {
	    /* Invokes */
	case INST_INVOKE_STK1:
	case INST_INVOKE_STK4:







|
|













|















|
|
|
|







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
}

/*
 * ---------------------------------------------------------------------
 *
 * IsCompactibleCompileEnv --
 *
 *	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, 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 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
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SubstObj --
 *
 *	This function performs the substitutions specified on the given string
 *	as described in the user documentation for the "subst" Tcl command.
 *
 * Results:
 *	A Tcl_Obj* containing the substituted string, or NULL to indicate that
 *	an error occurred.
 *
 * Side effects:
 *	See the user documentation.







|
|







1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SubstObj --
 *
 *	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
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NRSubstObj --
 *
 *	Request substitution of a Tcl value by the NR stack.
 *
 * Results:
 *	Returns 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
 *	the bytecode and store the result in the interp.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_NRSubstObj(







|


|



|







1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NRSubstObj --
 *
 *	Adds substitution within the value of objPtr to the NR execution stack.
 *
 * Results:
 *	TCL_OK.
 *
 * Side effects:
 *	Compiles objPtr into bytecode that performs the substitutions as
 *	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
}

/*
 *----------------------------------------------------------------------
 *
 * CompileSubstObj --
 *
 *	Compile a Tcl value into ByteCode implementing its substitution, as
 *	governed by flags.
 *
 * Results:
 *	A (ByteCode *) is returned 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);

    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);
	    codePtr = NULL;
	}
    }
    if (codePtr == NULL) {
	CompileEnv compEnv;
	size_t 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);








|
|


|



















|











|





|







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
}

/*
 *----------------------------------------------------------------------
 *
 * CompileSubstObj --
 *
 *	Compiles a value into bytecode that performs substitution within the
 *	value, as governed by flags.
 *
 * Results:
 *	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;

    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_StoreInternalRep(objPtr, &substCodeType, NULL);
	    codePtr = NULL;
	}
    }
    if (codePtr == NULL) {
	CompileEnv compEnv;
	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);

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
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * 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);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

static void
ReleaseCmdWordData(
    ExtCmdLoc *eclPtr)
{
    int i;

    if (eclPtr->type == TCL_LOCATION_SOURCE) {
	Tcl_DecrRefCount(eclPtr->path);
    }
    for (i=0 ; i<eclPtr->nuloc ; i++) {
	Tcl_Free(eclPtr->loc[i].line);
    }







|
|
|


















|









|







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
}

/*
 *----------------------------------------------------------------------
 *
 * FreeSubstCodeInternalRep --
 *
 *	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;

    ByteCodeGetInternalRep(objPtr, &substCodeType, codePtr);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

static void
ReleaseCmdWordData(
    ExtCmdLoc *eclPtr)
{
    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
}

/*
 *----------------------------------------------------------------------
 *
 * TclFreeCompileEnv --
 *
 *	Free the storage allocated in a CompileEnv compilation environment
 *	structure.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Allocated storage in the CompileEnv structure is freed. Note that 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.
 *
 *----------------------------------------------------------------------







|






|







1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
}

/*
 *----------------------------------------------------------------------
 *
 * TclFreeCompileEnv --
 *
 *	Frees the storage allocated in a CompileEnv compilation environment
 *	structure.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	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
    }
    if (envPtr->iPtr) {
	/*
	 * We never converted to Bytecode, so free the things we would
	 * have transferred to it.
	 */

	int i;
	LiteralEntry *entryPtr = envPtr->literalArrayPtr;
	AuxData *auxDataPtr = envPtr->auxDataArrayPtr;

	for (i = 0;  i < envPtr->literalArrayNext;  i++) {
	    TclReleaseLiteral((Tcl_Interp *)envPtr->iPtr, entryPtr->objPtr);
	    entryPtr++;
	}







|







1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
    }
    if (envPtr->iPtr) {
	/*
	 * We never converted to Bytecode, so free the things we would
	 * have transferred to it.
	 */

	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
}

/*
 *----------------------------------------------------------------------
 *
 * TclWordKnownAtCompileTime --
 *
 *	Test 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
 *	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.
 *







|
>


|







1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
}

/*
 *----------------------------------------------------------------------
 *
 * TclWordKnownAtCompileTime --
 *
 *	Determines whether the value of a token is completely known at compile
 *	time.
 *
 * Results:
 *	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
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileScript --
 *
 *	Compile 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
 *	contains an error message.
 *
 * Side effects:
 *	Adds instructions to envPtr to evaluate the script at runtime.
 *
 *----------------------------------------------------------------------
 */








|


<
>
>
|
<







1791
1792
1793
1794
1795
1796
1797
1798
1799
1800

1801
1802
1803

1804
1805
1806
1807
1808
1809
1810
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileScript --
 *
 *	Compiles a Tcl script in a string.
 *
 * Results:

 *
 *	A standard Tcl result. If an error occurs, an
 *	error message is left in the interpreter's result.

 *
 * 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
    Tcl_Interp *interp,
    Tcl_Obj *cmdObj,
    CompileEnv *envPtr)
{
    const char *bytes;
    Command *cmdPtr;
    int cmdLitIdx, extraLiteralFlags = LITERAL_CMD_NAME;
    size_t length;

    cmdPtr = (Command *) Tcl_GetCommandFromObj(interp, cmdObj);
    if ((cmdPtr != NULL) && (cmdPtr->flags & CMD_VIA_RESOLVER)) {
	extraLiteralFlags |= LITERAL_UNSHARED;
    }

    bytes = TclGetStringFromObj(cmdObj, &length);







|







1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
    Tcl_Interp *interp,
    Tcl_Obj *cmdObj,
    CompileEnv *envPtr)
{
    const char *bytes;
    Command *cmdPtr;
    int cmdLitIdx, extraLiteralFlags = LITERAL_CMD_NAME;
    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
	}
	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
     * 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
     * stack top changes by (1-wordIdx).
     *
     * Note that 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 depth = TclGetStackDepth(envPtr);

    /*
     * Emit 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.
     */

    switch (envPtr->atCmdStart) {
    case 0:
	unwind = tclInstructionTable[INST_START_CMD].numBytes;
	TclEmitInstInt4(INST_START_CMD, 0, envPtr);
	incrOffset = envPtr->codeNext - envPtr->codeStart;







|



|


|















|
>



|


|
|
|
|
|
|
|







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
	}
	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.  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
     * stack top changes by (1-wordIdx).
     *
     * 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;
    Tcl_Size incrOffset = -1;
    int depth = TclGetStackDepth(envPtr);

    /*
     * Emission of the INST_START_CMD instruction is controlled by the value of
     * envPtr->atCmdStart:
     *
     * 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
	/* Nothing to do */
	;
    }

    if (TCL_OK == TclAttemptCompileProc(interp, parsePtr, 1, cmdPtr, envPtr)) {
	if (incrOffset >= 0) {
	    /*
	     * We successfully compiled a command.  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);







|







1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
	/* Nothing to do */
	;
    }

    if (TCL_OK == TclAttemptCompileProc(interp, parsePtr, 1, cmdPtr, envPtr)) {
	if (incrOffset >= 0) {
	    /*
	     * 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
    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;
    int depth = TclGetStackDepth(envPtr);

    assert (parsePtr->numWords > 0);

    /* Pre-Compile */

    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
     * 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,







|
|
|
|
|


|

|








|







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
    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;
    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 ((int)parsePtr->numWords > 0);

    /* Precompile */

    TclNewObj(cmdObj);
    envPtr->numCommands++;
    EnterCmdStartData(envPtr, cmdIdx,
	    parsePtr->commandStart - envPtr->source, startCodeOffset);

    /*
     * TIP #280. Scan the words and compute the extended location information.
     * 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
	    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);
	    if (expand) {
		/* We need to expand, but compileProc cannot. */
		cmdPtr = NULL;
	    }
	}
    }

    /* If cmdPtr != NULL, we will 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);
	}

	if (expand) {
	    CompileExpanded(interp, parsePtr->tokenPtr,
		    cmdKnown ? cmdObj : NULL, parsePtr->numWords, envPtr);
	} else {
	    TclCompileInvocation(interp, parsePtr->tokenPtr,
		    cmdKnown ? cmdObj : NULL, 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
     */

    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
				 * 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).
     */
    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);
	TclCompileSyntaxError(interp, envPtr);
	return;
    }





    /* 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));

      do {
	const char *next;

	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;
	}

#ifdef TCL_COMPILE_DEBUG
	/*
	 * 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");
	}
#endif

	/*
	 * 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);

	/*
	 * Advance parser to the next command in the script.
	 */

	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;
	}

	/*
	 * Avoid stack exhaustion by too many nested calls of TclCompileScript
	 * (considering interp recursionlimit).
	 */
	iPtr->numLevels++;

	lastCmdIdx = CompileCommandTokens(interp, parsePtr, envPtr);

	iPtr->numLevels--;

	/*
	 * 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);

      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







|







|






|




|


|











|
|



















|

















|
|
|
|



|
|




>
>
>
>


|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|

|
|

|
|
|
|

|
|
|
|
|
|


|
|
|
|

|
|
|
|
|
|
|


|
|
|
|

|
|
|

|
|
|

|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|

|

|

|
|
|

|
|
|
|
|

|







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
	    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, (int)parsePtr->numWords);
	    if (expand) {
		/* We need to expand, but compileProc cannot. */
		cmdPtr = NULL;
	    }
	}
    }

    /* 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, (int)parsePtr->numWords);
	}

	if (expand) {
	    CompileExpanded(interp, parsePtr->tokenPtr,
		    cmdKnown ? cmdObj : NULL, (int)parsePtr->numWords, envPtr);
	} else {
	    TclCompileInvocation(interp, parsePtr->tokenPtr,
		    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 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. */
    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.
     * 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", (char *)NULL);
	TclCompileSyntaxError(interp, envPtr);
	return;
    }

    if (numBytes < 0) {
	numBytes = strlen(script);
    }

    /* Each iteration compiles one command from the script. */

    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", (void *)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;

	    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;
	    }

#ifdef TCL_COMPILE_DEBUG
	    /*
	     * 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");
	    }
#endif

	    /*
	     * 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);

	    /*
	     * Advance parser to the next command in the script.
	     */

	    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 (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++;

	    lastCmdIdx = CompileCommandTokens(interp, parsePtr, envPtr);

	    iPtr->numLevels--;

	    /*
	     * 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);

	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
}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	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.
 *







|
|







2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileTokens --
 *
 *	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
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;

    /*
     * 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) == ':')) {
	    localVarName = -1;
	    break;
	} else if ((*p == '(')
		&& (tokenPtr->numComponents == 1)
		&& (*(name + nameBytes - 1) == ')')) {
	    localVarName = 0;
	    break;
	}
    }

    /*
     * Either push the variable's name, or find its index in the array







|
>
|










|


|

|







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
void
TclCompileVarSubst(
    Tcl_Interp *interp,
    Tcl_Token *tokenPtr,
    CompileEnv *envPtr)
{
    const char *p, *name = tokenPtr[1].start;
    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[0] == ':') && (i < nameBytes-1) && (p[1] == ':')) {
	    localVarName = -1;
	    break;
	} else if ((p[0] == '(')
		&& (tokenPtr->numComponents == 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
}

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.
				 * 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;
    size_t length;
    unsigned char *entryCodeNext = envPtr->codeNext;
#define NUM_STATIC_POS 20
    int isLiteral, maxNumCL, numCL;

    int *clPosition = NULL;
    int depth = TclGetStackDepth(envPtr);


    /*
     * 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
     * locations of all continuation lines we find in this literal, if any.
     * 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.
     * 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.
     */

    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));
    }

    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
	     * 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
	     * 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.
	     */

	    if ((length == 1) && (buffer[0] == ' ') &&
		(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[numCL] = clPos;
		    numCL ++;
		}
		adjust++;
	    }
	    break;







|






|



|
>
|

>


<
|
|
<
|

|
|
<
|
>
|
|















|



















|
|



|
|
|
|
<
|
|



|





|
|







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
}

void
TclCompileTokens(
    Tcl_Interp *interp,		/* Used for error and status reporting. */
    Tcl_Token *tokenPtr,	/* Pointer to first in an array of tokens to
				 * compile. */
    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] = "";
    Tcl_Size i, numObjsToConcat, adjust;
    size_t length;
    unsigned char *entryCodeNext = envPtr->codeNext;
#define NUM_STATIC_POS 20
    int isLiteral;
    Tcl_Size maxNumCL, numCL;
    Tcl_Size *clPosition = NULL;
    int depth = TclGetStackDepth(envPtr);
    int count = count1;

    /*

     * If this is actually a literal, handle continuation lines by
     * preallocating a small table to store the locations of any continuation

     * lines found in this literal.  The table is extended if needed.
     *
     * Note: In contrast with the analagous code in 'TclSubstTokens()' the
     * 'adjust' variable seems unneeded here.  The code which merges

     * 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 = (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 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.
	     *
	     * 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

	     * thing is a table of everything is not needed, just the number of
	     * lines to to add as correction.
	     */

	    if ((length == 1) && (buffer[0] == ' ') &&
		    (tokenPtr->start[1] == '\n')) {
		if (isLiteral) {
		    int clPos = Tcl_DStringLength(&textBuffer);

		    if (numCL >= maxNumCL) {
			maxNumCL *= 2;
			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

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * Results:
 *	The return value is 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.
				 * Must be at least 1. */
    CompileEnv *envPtr)		/* Holds the resulting instructions. */
{


    if ((count == 1) && (tokenPtr->type == TCL_TOKEN_TEXT)) {
	/*
	 * Handle the common case: if 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.
	 */

	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
 *	appear as command words.
 *
 * Results:
 *	The return value is 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
				 * inline. */
    int numWords,		/* 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;


    /*
     * 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)) {







|
|
|
|


|













|



>
>


|






|
|
|













|
|
|
<


|














|






>







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

/*
 *----------------------------------------------------------------------
 *
 * TclCompileCmdWord --
 *
 *	Given an array of parse tokens for a word containing one or more Tcl
 *	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:
 *	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. */
    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)) {
	/*
	 * 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 {
	/*
	 * 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, 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.

 *
 * Results:
 *	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
				 * inline. */
    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
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileNoOp --
 *
 *	Function called to compile no-op's
 *
 * Results:
 *	The return value is TCL_OK, indicating successful compilation.
 *
 * 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.
 *
 *----------------------------------------------------------------------







|


|







2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileNoOp --
 *
 *	Compiles no-op's
 *
 * Results:
 *	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
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    Tcl_Token *tokenPtr;
    int i;

    tokenPtr = parsePtr->tokenPtr;
    for (i = 1; i < 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
 *	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
 *	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;

    for (i = 0;  i < envPtr->literalArrayNext; i++) {
	if (objPtr == TclFetchLiteral(envPtr, i)) {
	    /*
	     * Prevent circular reference where the bytecode intrep 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.
	     */
	    size_t 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;







|
















|






|

















|




|







|

|







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
    TCL_UNUSED(Command *),
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    Tcl_Token *tokenPtr;
    int i;

    tokenPtr = parsePtr->tokenPtr;
    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 --
 *
 *	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
 *	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)
{
    Tcl_Size i;

    for (i = 0;  i < envPtr->literalArrayNext; i++) {
	if (objPtr == TclFetchLiteral(envPtr, i)) {
	    /*
	     * 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 internalrep.
	     */
	    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
    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.




     */

    structureSize = sizeof(ByteCode);
    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) {







>
>
>
>


|







2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
    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 = 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
    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);
    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);







|







2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
    codePtr->numLitObjects = numLitObjects;
    codePtr->numExceptRanges = envPtr->exceptArrayNext;
    codePtr->numAuxDataItems = envPtr->auxDataArrayNext;
    codePtr->numCmdLocBytes = cmdLocBytes;
    codePtr->maxExceptDepth = envPtr->maxExceptDepth;
    codePtr->maxStackDepth = envPtr->maxStackDepth;

    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
    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);
    return codePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclFindCompiledLocal --







|







2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
    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.
     */

    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
 * 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
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. */
    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;
    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;

	if (!cachePtr || !name) {
	    return -1;
	}

	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;
    }

    if (name != NULL) {
	int localCt = procPtr->numCompiledLocals;

	localPtr = procPtr->firstLocalPtr;
	for (i = 0;  i < localCt;  i++) {
	    if (!TclIsVarTemporary(localPtr)) {
		char *localName = localPtr->name;

		if ((nameBytes == localPtr->nameLength) &&







|




|





|
|


















|


|











|



|







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
 * Side effects:
 *	Creates and registers a new local variable if create is 1 and the
 *	variable is unknown, or if the name is NULL.
 *
 *----------------------------------------------------------------------
 */

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. */
    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;
    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;
	Tcl_Size len;

	if (!cachePtr || !name) {
	    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 TCL_INDEX_NONE;
    }

    if (name != NULL) {
	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

    /*
     * Create a new variable if appropriate.
     */

    if (create || (name == NULL)) {
	localVar = procPtr->numCompiledLocals;
	localPtr = (CompiledLocal *)Tcl_Alloc(offsetof(CompiledLocal, name) + nameBytes + 1);
	if (procPtr->firstLocalPtr == NULL) {
	    procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
	} else {
	    procPtr->lastLocalPtr->nextPtr = localPtr;
	    procPtr->lastLocalPtr = localPtr;
	}
	localPtr->nextPtr = NULL;







|







3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114

    /*
     * Create a new variable if appropriate.
     */

    if (create || (name == NULL)) {
	localVar = procPtr->numCompiledLocals;
	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
}

/*
 *----------------------------------------------------------------------
 *
 * TclExpandCodeArray --
 *
 *	Procedure that uses malloc to allocate more storage for a CompileEnv's
 *	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.
 *
 *----------------------------------------------------------------------
 */

void
TclExpandCodeArray(
    void *envArgPtr)		/* Points to the CompileEnv whose code array







|
<





|
|
|







3131
3132
3133
3134
3135
3136
3137
3138

3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
}

/*
 *----------------------------------------------------------------------
 *
 * TclExpandCodeArray --
 *
 *	Uses malloc to allocate more storage for a CompileEnv's code array.

 *
 * Results:
 *	None.
 *
 * Side effects:
 *	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
    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.
	 */

	unsigned char *newPtr = (unsigned char *)Tcl_Alloc(newBytes);

	memcpy(newPtr, envPtr->codeStart, currBytes);
	envPtr->codeStart = newPtr;
	envPtr->mallocedCodeArray = 1;







|
|







3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
    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->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
 */

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
				 * being set. */
    int srcOffset,		/* Offset of first char of the command. */
    int 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 >= 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).







|

|
|



|
|







3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
 */

static void
EnterCmdStartData(
    CompileEnv *envPtr,		/* Points to the compilation environment
				 * structure in which to enter command
				 * location information. */
    Tcl_Size cmdIndex,		/* Index of the command whose start data is
				 * being set. */
    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 %" 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
	    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;
}

/*
 *----------------------------------------------------------------------
 *
 * EnterCmdExtentData --
 *







|
|







3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
	    Tcl_Panic("EnterCmdStartData: cmd map not sorted by code offset");
	}
    }

    cmdLocPtr = &envPtr->cmdMapPtr[cmdIndex];
    cmdLocPtr->codeOffset = codeOffset;
    cmdLocPtr->srcOffset = srcOffset;
    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
 */

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
				 * length data is being set. */
    int numSrcBytes,		/* Number of command source chars. */
    int 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 > envPtr->cmdMapEnd) {
	Tcl_Panic("EnterCmdExtentData: missing start data for command %d",
		cmdIndex);
    }

    cmdLocPtr = &envPtr->cmdMapPtr[cmdIndex];
    cmdLocPtr->numSrcBytes = numSrcBytes;
    cmdLocPtr->numCodeBytes = numCodeBytes;
}







|

|
|



|
|



|







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
 */

static void
EnterCmdExtentData(
    CompileEnv *envPtr,		/* Points to the compilation environment
				 * structure in which to enter command
				 * location information. */
    Tcl_Size cmdIndex,		/* Index of the command whose source and code
				 * length data is being set. */
    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 %" TCL_Z_MODIFIER "u", cmdIndex);
    }

    if (cmdIndex > envPtr->cmdMapEnd) {
	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
 */

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_Token *tokenPtr,
    const char *cmd,
    int numWords,
    int line,
    int *clNext,
    int **wlines,
    CompileEnv *envPtr)
{
    ECL *ePtr;
    const char *last;

    int wordIdx, wordLine, *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->nline = numWords;
    wwlines = (int *)Tcl_Alloc(numWords * sizeof(int));

    last = cmd;
    wordLine = line;
    wordNext = clNext;
    for (wordIdx=0 ; wordIdx<numWords;
	    wordIdx++, tokenPtr += tokenPtr->numComponents + 1) {
	TclAdvanceLines(&wordLine, last, tokenPtr->start);







|


|
|
|
|




>
|


















|
|

|







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
 */

static void
EnterCmdWordData(
    ExtCmdLoc *eclPtr,		/* Points to the map environment structure in
				 * which to enter command location
				 * information. */
    Tcl_Size srcOffset,		/* Offset of first char of the command. */
    Tcl_Token *tokenPtr,
    const char *cmd,
    Tcl_Size numWords,
    Tcl_Size line,
    Tcl_Size *clNext,
    Tcl_Size **wlines,
    CompileEnv *envPtr)
{
    ECL *ePtr;
    const char *last;
    Tcl_Size wordIdx, wordLine;
    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 = (Tcl_Size *)Tcl_Alloc(numWords * sizeof(Tcl_Size));
    ePtr->next = (Tcl_Size **)Tcl_Alloc(numWords * sizeof(Tcl_Size *));
    ePtr->nline = numWords;
    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
 *	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
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;

    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 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
 *	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.
 *
 *----------------------------------------------------------------------
 */

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;
    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);
	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
	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;
    auxPtr = &envPtr->exceptAuxArrayPtr[index];
    auxPtr->supportsContinue = 1;
    auxPtr->stackDepth = envPtr->currStackDepth;
    auxPtr->expandTarget = envPtr->expandCount;
    auxPtr->expandTargetDepth = -1;
    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
 *	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;
    ExceptionRange *rangePtr = envPtr->exceptArrayPtr + i;

    while (i > 0) {
	rangePtr--; i--;

	if (CurrentOffset(envPtr) >= rangePtr->codeOffset &&
		(rangePtr->numCodeBytes == -1 || CurrentOffset(envPtr) <
			rangePtr->codeOffset+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
 *	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);
	} else {
	    auxPtr->breakTargets =
		    (unsigned int *)Tcl_Alloc(sizeof(int) * auxPtr->allocBreakTargets);
	}
    }
    auxPtr->breakTargets[auxPtr->numBreakTargets - 1] = CurrentOffset(envPtr);
    TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}

void







|
|
|
|
|




|















|













|





|
|
|



















|




















|
|


|







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
	envPtr->exceptArrayEnd = newElems;
    }
    envPtr->exceptArrayNext++;

    rangePtr = &envPtr->exceptArrayPtr[index];
    rangePtr->type = type;
    rangePtr->nestingLevel = envPtr->exceptDepth;
    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 = 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
 *	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)
{
    size_t i = envPtr->exceptArrayNext;
    ExceptionRange *rangePtr = envPtr->exceptArrayPtr + i;

    while (i > 0) {
	rangePtr--; i--;

	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 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 = (size_t *)Tcl_Realloc(auxPtr->breakTargets,
		    sizeof(size_t) * auxPtr->allocBreakTargets);
	} else {
	    auxPtr->breakTargets =
		    (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
	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);
	} else {
	    auxPtr->continueTargets =
		    (unsigned int *)Tcl_Alloc(sizeof(int) * 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
 *	the auxiliary stack to pop.
 *
 * ---------------------------------------------------------------------
 */

void
TclCleanupStackForBreakContinue(
    CompileEnv *envPtr,
    ExceptionAux *auxPtr)
{
    int 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,
		envPtr);
	envPtr->currStackDepth = auxPtr->expandTargetDepth;
    }
    toPop = envPtr->currStackDepth - auxPtr->stackDepth;
    while (toPop --> 0) {
	TclEmitOpcode(INST_POP, envPtr);
    }







|
|


|












|
|










|






|







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
	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 = (size_t *)Tcl_Realloc(auxPtr->continueTargets,
		    sizeof(size_t) * auxPtr->allocContinueTargets);
	} else {
	    auxPtr->continueTargets =
		    (size_t *)Tcl_Alloc(sizeof(size_t) * auxPtr->allocContinueTargets);
	}
    }
    auxPtr->continueTargets[auxPtr->numContinueTargets - 1] =
	    CurrentOffset(envPtr);
    TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}

/*
 * ---------------------------------------------------------------------
 *
 * TclCleanupStackForBreakContinue --
 *
 *	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)
{
    size_t savedStackDepth = envPtr->currStackDepth;
    int toPop = envPtr->expandCount - auxPtr->expandTarget;

    if (toPop > 0) {
	while (toPop --> 0) {
	    TclEmitOpcode(INST_EXPAND_DROP, envPtr);
	}
	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
    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++) {
	ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i];
	ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[i];

	/*
	 * Ignore loops unless they're still being built.
	 */

	if (rangePtr->codeOffset > CurrentOffset(envPtr)) {
	    continue;
	}
	if (rangePtr->numCodeBytes != -1) {
	    continue;
	}

	/*
	 * Adequate condition: further out loops and further in exceptions
	 * 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.
     */

    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
 *	target offsets have been set.
 *
 * ---------------------------------------------------------------------
 */

void
TclFinalizeLoopExceptionRange(







|







|


|




|









|












|







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
    TclEmitOpcode(INST_EXPAND_START, envPtr);

    /*
     * Update inner exception ranges with information about the environment
     * where this expansion started.
     */

    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 ((int)rangePtr->codeOffset > CurrentOffset(envPtr)) {
	    continue;
	}
	if (rangePtr->numCodeBytes != TCL_INDEX_NONE) {
	    continue;
	}

	/*
	 * Adequate condition: loops further out and exceptions further in
	 * don't actually need this information.
	 */

	if (auxPtr->expandTarget == envPtr->expandCount) {
	    auxPtr->expandTargetDepth = envPtr->currStackDepth;
	}
    }

    /*
     * 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.
 *	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
    }

    /*
     * 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++) {
	site = envPtr->codeStart + auxPtr->breakTargets[i];
	offset = rangePtr->breakOffset - auxPtr->breakTargets[i];
	TclUpdateInstInt4AtPc(INST_JUMP4, offset, site);
    }
    for (i=0 ; i<auxPtr->numContinueTargets ; i++) {
	site = envPtr->codeStart + auxPtr->continueTargets[i];
	if (rangePtr->continueOffset == -1) {
	    int j;

	    /*
	     * WTF? Can't bind, so revert to an INST_CONTINUE. Not enough
	     * space to do anything else.
	     */








|




|

|







3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
    }

    /*
     * 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<(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<(int)auxPtr->numContinueTargets ; i++) {
	site = envPtr->codeStart + auxPtr->continueTargets[i];
	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
}

/*
 *----------------------------------------------------------------------
 *
 * TclCreateAuxData --
 *
 *	Procedure that 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.
 *
 * Side effects:
 *	If there is not enough room in the CompileEnv's AuxData array, the
 *	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.
 *
 *----------------------------------------------------------------------
 */

int
TclCreateAuxData(
    ClientData 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. */
    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 newBytes = newElems * sizeof(AuxData);

	if (envPtr->mallocedAuxDataArray) {
	    envPtr->auxDataArrayPtr =
		    (AuxData *)Tcl_Realloc(envPtr->auxDataArrayPtr, newBytes);
	} else {
	    /*







|





|


|
<
<
<
|
<



|

|






|












|







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
}

/*
 *----------------------------------------------------------------------
 *
 * TclCreateAuxData --
 *
 *	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:
 *	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, its size



 *	is doubled.

 *----------------------------------------------------------------------
 */

Tcl_Size
TclCreateAuxData(
    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. */
{
    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);
	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
}

/*
 *----------------------------------------------------------------------
 *
 * TclExpandJumpFixupArray --
 *
 *	Procedure that uses malloc to allocate more storage for a jump fixup
 *	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







|
<







3853
3854
3855
3856
3857
3858
3859
3860

3861
3862
3863
3864
3865
3866
3867
}

/*
 *----------------------------------------------------------------------
 *
 * TclExpandJumpFixupArray --
 *
 *	Uses malloc to allocate more storage for a jump fixup 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
    /*
     * 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 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







|







3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
    /*
     * 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);
    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
}

/*
 *----------------------------------------------------------------------
 *
 * TclEmitForwardJump --
 *
 *	Procedure to emit a two-byte forward jump of kind "jumpType". Since
 *	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.



 *
 * 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







|
<
<
|
>
>
>







3932
3933
3934
3935
3936
3937
3938
3939


3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
}

/*
 *----------------------------------------------------------------------
 *
 * TclEmitForwardJump --
 *
 *	Emits a two-byte forward jump of kind "jumpType".  Also initializes a


 *	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
}

/*
 *----------------------------------------------------------------------
 *
 * 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.

 *
 * 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.
 *
 * 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.







|
|
|
|
|
>


|
|
|







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
}

/*
 *----------------------------------------------------------------------
 *
 * TclFixupForwardJump --
 *
 *	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, 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
	    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.
     */

    if ((envPtr->codeNext + 3) > envPtr->codeEnd) {
	TclExpandCodeArray(envPtr);
    }
    jumpPc = envPtr->codeStart + jumpFixupPtr->codeOffset;
    numBytes = envPtr->codeNext-jumpPc-2;







|
|
|
|







4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
	    TclUpdateInstInt1AtPc(INST_JUMP_FALSE1, jumpDist, jumpPc);
	    break;
	}
	return 0;
    }

    /*
     * 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
    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) {
		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++) {
	ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[k];
	int i;

	for (i=0 ; i<auxPtr->numBreakTargets ; i++) {
	    if (jumpFixupPtr->codeOffset < auxPtr->breakTargets[i]) {
		auxPtr->breakTargets[i] += 3;
	    }
	}
	for (i=0 ; i<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
 *	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
 *	structures should not be held across this call.
 *
 *----------------------------------------------------------------------
 */

void
TclEmitInvoke(







|












|



|




|














|









|







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
    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 != 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 < (int)envPtr->exceptArrayNext ; k++) {
	ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[k];
	int i;

	for (i=0 ; i<(int)auxPtr->numBreakTargets ; i++) {
	    if (jumpFixupPtr->codeOffset < auxPtr->breakTargets[i]) {
		auxPtr->breakTargets[i] += 3;
	    }
	}
	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 --
 *
 *	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
 *	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
	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
     * stack).
     *
     * These must be done separately; 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 = 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 = NULL;
    } else {
	breakRange = auxBreakPtr - envPtr->exceptAuxArrayPtr;
    }

    if (auxBreakPtr != NULL || auxContinuePtr != NULL) {
	loopRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr);







|
|
<

|
|







|









|
|







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
	arg2 = 0;
	expandCount = 1;
	break;
    }
    va_end(argList);

    /*
     * If the exceptions is for break or continue handle it with special
     * handling exception range so the stack may be correctly unwound.

     *
     * 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+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+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

    /*
     * 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;
	JumpFixup nonTrapFixup;

	if (auxBreakPtr != NULL) {
	    auxBreakPtr = envPtr->exceptAuxArrayPtr + breakRange;
	}
	if (auxContinuePtr != NULL) {
	    auxContinuePtr = envPtr->exceptAuxArrayPtr + continueRange;







|
|







4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283

    /*
     * If we're generating a special wrapper exception range, we need to
     * finish that up now.
     */

    if (auxBreakPtr != NULL || auxContinuePtr != NULL) {
	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
}

/*
 *----------------------------------------------------------------------
 *
 * EncodeCmdLocMap --
 *
 *	Encode the command location information for some compiled code into a
 *	ByteCode structure. The encoded command location map is stored as
 *	three adjacent byte sequences.
 *
 * Results:
 *	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
 *	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;

    int numCmds = envPtr->numCommands;
    unsigned char *p = startPtr;
    int codeDelta, codeLen, srcDelta, srcLen, prevOffset;
    int i;

    /*
     * Encode the code offset for each command as a sequence of deltas.
     */

    codePtr->codeDeltaStart = p;
    prevOffset = 0;







|

|


|



|


















>
|

<
|







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
}

/*
 *----------------------------------------------------------------------
 *
 * EncodeCmdLocMap --
 *
 *	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.
 *
 * Results:
 *	A pointer to the first byte after the encoded command location
 *	information.
 *
 * Side effects:
 *	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;
    Tcl_Size numCmds = envPtr->numCommands;
    unsigned char *p = startPtr;

    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

#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
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Accumulates aggregate code-related statistics in the interpreter's
 *	ByteCodeStats structure. Records statistics specific to a ByteCode in







|
|
|







4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563

#ifdef TCL_COMPILE_STATS
/*
 *----------------------------------------------------------------------
 *
 * RecordByteCodeStats --
 *
 *	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
    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->totalByteCodeBytes += (double) codePtr->structureSize;
    statsPtr->currentSrcBytes += (double) codePtr->numSrcBytes;
    statsPtr->currentByteCodeBytes += (double) codePtr->structureSize;

    statsPtr->srcCount[TclLog2(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);







|

|


|







4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
    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->totalByteCodeBytes += (double) codePtr->structureSize;
    statsPtr->currentSrcBytes += (double) (int)codePtr->numSrcBytes;
    statsPtr->currentByteCodeBytes += (double) codePtr->structureSize;

    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.

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    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
				 * to find the most deeply-nested range
				 * surrounding a PC at runtime. */
    int 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
				 * 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
				 * range when processing a continue
				 * command. */
    int 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
				 * 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
				 * 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
				 * 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
				 * targeted to the place where this loop
				 * exception will be bound to. */
    unsigned int *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
				 * targeted to the place where this loop
				 * exception will be bound to. */
    unsigned int *continueTargets; /* 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. */
    int allocContinueTargets;	/* 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. */
} 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
				 * command. */
    int **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
				 * 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'. */
} 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







|


|

|
|

|




|















|



|




|




|


|





|
|


|





|











|
|
|
|














|
|
|

|






|





|
|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    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. */
    Tcl_Size nestingLevel;		/* Static depth of the exception range. Used
				 * to find the most deeply-nested range
				 * surrounding a PC at runtime. */
    Tcl_Size codeOffset;		/* Offset of the first instruction byte of the
				 * code range. */
    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. */
    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. */
    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. */
    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. */
    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. */
    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. */
    Tcl_Size numBreakTargets;	/* The number of [break]s that want to be
				 * targeted to the place where this loop
				 * exception will be bound to. */
    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. */
    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; /* 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;	/* 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 {
    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 {
    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. */
    Tcl_Size **next;			/* Transient information used by the compiler
				 * for tracking of hidden continuation
				 * lines. */
} ECL;

typedef struct {
    int type;			/* Context type. */
    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). */
    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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
 * 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);

/*
 * 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.
 */







|







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
 * the AuxData structure.
 */

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.
 */
286
287
288
289
290
291
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
				 * 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. */
    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
				 * execute the code. Set by compilation
				 * procedures before returning. */
    int 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.*/




    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. */
    int mallocedLiteralArray;	/* 1 if object array was expanded and objArray
				 * points into the heap, else 0. */
    ExceptionRange *exceptArrayPtr;
    				/* Points to start of the ExceptionRange
				 * array. */
    int 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
				 * entry. */

    int mallocedExceptArray;	/* 1 if ExceptionRange array was expanded and
				 * exceptArrayPtr points in heap, else 0. */

    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. */
    int mallocedCmdMap;		/* 1 if command map array was expanded and
				 * cmdMapPtr points in the heap, else 0. */




    AuxData *auxDataArrayPtr;	/* Points to auxiliary data array start. */
    int 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
				 * auxDataArrayPtr points in heap else 0. */

    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
				 * 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
				 * 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
				 * 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







|





|
|

|

|


|











>
>
>
>


|
|





|



|

>
|
<
>









|


>
>
>
>

|



|
>
|
<
>
















|








|



|







286
287
288
289
290
291
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
				 * 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. */
    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. */
    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. */
    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. */
    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
				 * array. */
    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. */
    Tcl_Size exceptArrayEnd;		/* Index after the last ExceptionRange array
				 * entry. */
#if TCL_MAJOR_VERSION < 9
    int mallocedExceptArray;

#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. */
    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. */
    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. */
    Tcl_Size auxDataArrayEnd;	/* Index after last aux data array entry. */
#if TCL_MAJOR_VERSION < 9
    int mallocedAuxDataArray;

#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'. */
    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). */
    Tcl_Size expandCount;		/* Number of INST_EXPAND_START instructions
				 * encountered that have not yet been paired
				 * with a corresponding
				 * INST_INVOKE_EXPANDED. */
    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

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
				 * 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
				 * 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
				 * 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
				 * 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
				 * location information. */
    int maxExceptDepth;		/* Maximum nesting level of ExceptionRanges;
				 * -1 if no ranges were compiled. */
    int 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. */







|







|



|




|














|
|
|
|
|
|
|

|
|
|







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

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. */
    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. */
    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. */
    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 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. */
    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. */
    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. */
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
				 * 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)			\
    do {								\
	Tcl_ObjIntRep ir;						\
	ir.twoPtrValue.ptr1 = (codePtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), (typePtr), &ir);			\
    } while (0)



#define ByteCodeGetIntRep(objPtr, typePtr, codePtr)			\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((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.,







|

|


|




|

|
|







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
				 * variables. */
#ifdef TCL_COMPILE_STATS
    Tcl_Time createTime;	/* Absolute time when the ByteCode was
				 * created. */
#endif /* TCL_COMPILE_STATS */
} ByteCode;

#define ByteCodeSetInternalRep(objPtr, typePtr, codePtr)			\
    do {								\
	Tcl_ObjInternalRep ir;						\
	ir.twoPtrValue.ptr1 = (codePtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreInternalRep((objPtr), (typePtr), &ir);			\
    } while (0)



#define ByteCodeGetInternalRep(objPtr, typePtr, codePtr)			\
    do {								\
	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.,
820
821
822
823
824
825
826






827
828
829
830
831
832
833
    INST_DICT_GET_DEF,

	/* TIP 461 */
	INST_STR_LT,
	INST_STR_GT,
	INST_STR_LE,
	INST_STR_GE,







    /* The last opcode */
    LAST_INST_OPCODE
};

/*
 * Table describing the Tcl bytecode instructions: their name (for displaying







>
>
>
>
>
>







830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
    INST_DICT_GET_DEF,

	/* 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
    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. */
    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];







|







877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
    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. */
    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
    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
				 * 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. */







|







912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
    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
				 * 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
				 * 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. */
    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")
				 * 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
				 * lists of the foreach command. */
    int 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
				 * 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
				 * structures describing each var list. The
				 * actual size of this field will be large
				 * enough to numVars indexes. THIS MUST BE THE







|
|














|
|















|

|

|







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
				 * to 5 bytes. */
} JumpFixup;

#define JUMPFIXUP_INIT_ENTRIES	10

typedef struct JumpFixupArray {
    JumpFixup *fixup;		/* Points to start of jump fixup 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 {
    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 {
    Tcl_Size numLists;		/* The number of both the variable and value
				 * lists of the foreach command. */
    Tcl_Size firstValueTemp;		/* Index of the first temp var in a proc frame
				 * used to point to a value list. */
    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
				 * structures describing each var list. The
				 * actual size of this field will be large
				 * enough to numVars indexes. THIS MUST BE THE
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
/*
 * 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
				 * 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;








|
|







1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
/*
 * 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 {
    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

/*
 *----------------------------------------------------------------
 * Procedures exported by tclBasic.c to be used within the engine.
 *----------------------------------------------------------------
 */


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,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCleanupStackForBreakContinue(CompileEnv *envPtr,
			    ExceptionAux *auxPtr);
MODULE_SCOPE void	TclCompileCmdWord(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int count,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileExpr(Tcl_Interp *interp, const char *script,
			    size_t numBytes, CompileEnv *envPtr, int optimize);
MODULE_SCOPE void	TclCompileExprWords(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int 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,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileSyntaxError(Tcl_Interp *interp,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileTokens(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, int count,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileVarSubst(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, CompileEnv *envPtr);
MODULE_SCOPE int	TclCreateAuxData(void *clientData,
			    const AuxDataType *typePtr, CompileEnv *envPtr);
MODULE_SCOPE int	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,
			    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,
			    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,







>



















|




|


|

|





|




|



|

|



|













|
|







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

/*
 *----------------------------------------------------------------
 * 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, 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, size_t count,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileExpr(Tcl_Interp *interp, const char *script,
			    Tcl_Size numBytes, CompileEnv *envPtr, int optimize);
MODULE_SCOPE void	TclCompileExprWords(Tcl_Interp *interp,
			    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, Tcl_Size numBytes,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileSyntaxError(Tcl_Interp *interp,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileTokens(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, size_t count,
			    CompileEnv *envPtr);
MODULE_SCOPE void	TclCompileVarSubst(Tcl_Interp *interp,
			    Tcl_Token *tokenPtr, CompileEnv *envPtr);
MODULE_SCOPE Tcl_Size	TclCreateAuxData(void *clientData,
			    const AuxDataType *typePtr, CompileEnv *envPtr);
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,
			    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, 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
			    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,
			    CompileEnv *envPtr);
MODULE_SCOPE int	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);
#endif
MODULE_SCOPE int	TclPrintInstruction(ByteCode *codePtr,
			    const unsigned char *pc);
MODULE_SCOPE void	TclPrintObject(FILE *outFile,
			    Tcl_Obj *objPtr, size_t maxChars);
MODULE_SCOPE void	TclPrintSource(FILE *outFile,
			    const char *string, size_t 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,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclSortingOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclVariadicOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclNoIdentOpCmd(void *clientData,
			    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_Obj **tosPtr);
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 int	TclPushProcCallFrame(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[], int isLambda);



/*
 *----------------------------------------------------------------
 * Macros and flag values used by Tcl bytecode compilation and execution
 * modules inside the Tcl core but not used outside.
 *----------------------------------------------------------------







|

|









|

|









|
<
<
|
<
<
|
<
<
|
<
<








|





|

>







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
			    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 size_t	TclLocalScalar(const char *bytes, size_t numBytes,
			    CompileEnv *envPtr);
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);
#endif
MODULE_SCOPE int	TclPrintInstruction(ByteCode *codePtr,
			    const unsigned char *pc);
MODULE_SCOPE void	TclPrintObject(FILE *outFile,
			    Tcl_Obj *objPtr, Tcl_Size maxChars);
MODULE_SCOPE void	TclPrintSource(FILE *outFile,
			    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 Tcl_ObjCmdProc	TclSingleOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclSortingOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclVariadicOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclNoIdentOpCmd;


#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,
			    Tcl_Size length, const unsigned char *pc,
			    Tcl_Obj **tosPtr);
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 int	TclPushProcCallFrame(void *clientData,
			    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.
 *----------------------------------------------------------------
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
 *
 * void TclAdjustStackDepth(int delta, CompileEnv *envPtr);
 */

#define TclAdjustStackDepth(delta, envPtr) \
    do {								\
	if ((delta) < 0) {						\
	    if ((envPtr)->maxStackDepth < (envPtr)->currStackDepth) {	\
		(envPtr)->maxStackDepth = (envPtr)->currStackDepth;	\
	    }								\
	}								\
	(envPtr)->currStackDepth += (delta);				\
    } while (0)

#define TclGetStackDepth(envPtr)		\
    ((envPtr)->currStackDepth)

#define TclSetStackDepth(depth, envPtr)		\
    (envPtr)->currStackDepth = (depth)

#define TclCheckStackDepth(depth, envPtr)				\
    do {								\
	int _dd = (depth);						\
	if (_dd != (envPtr)->currStackDepth) {				\
	    Tcl_Panic("bad stack depth computations: is %i, should be %i", \
		    (envPtr)->currStackDepth, _dd);		\
	}								\
    } while (0)

/*
 * Macro used to update the stack requirements. It is called by the macros
 * TclEmitOpCode, TclEmitInst1 and TclEmitInst4.
 * Remark that the very last instruction of a bytecode always reduces the







|














|
|
|
|







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
 *
 * void TclAdjustStackDepth(int delta, CompileEnv *envPtr);
 */

#define TclAdjustStackDepth(delta, envPtr) \
    do {								\
	if ((delta) < 0) {						\
	    if ((int)(envPtr)->maxStackDepth < (int)(envPtr)->currStackDepth) {	\
		(envPtr)->maxStackDepth = (envPtr)->currStackDepth;	\
	    }								\
	}								\
	(envPtr)->currStackDepth += (delta);				\
    } while (0)

#define TclGetStackDepth(envPtr)		\
    ((envPtr)->currStackDepth)

#define TclSetStackDepth(depth, envPtr)		\
    (envPtr)->currStackDepth = (depth)

#define TclCheckStackDepth(depth, envPtr)				\
    do {								\
	size_t _dd = (depth);						\
	if (_dd != (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, _dd);		\
	}								\
    } while (0)

/*
 * Macro used to update the stack requirements. It is called by the macros
 * TclEmitOpCode, TclEmitInst1 and TclEmitInst4.
 * Remark that the very last instruction of a bytecode always reduces the
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
 *
 * int TclFixupForwardJumpToHere(CompileEnv *envPtr, JumpFixup *fixupPtr,
 *				 int threshold);
 */

#define TclFixupForwardJumpToHere(envPtr, fixupPtr, threshold) \
    TclFixupForwardJump((envPtr), (fixupPtr),				\
	    (envPtr)->codeNext-(envPtr)->codeStart-(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:







|







1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
 *
 * int TclFixupForwardJumpToHere(CompileEnv *envPtr, JumpFixup *fixupPtr,
 *				 int threshold);
 */

#define TclFixupForwardJumpToHere(envPtr, fixupPtr, threshold) \
    TclFixupForwardJump((envPtr), (fixupPtr),				\
	    (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

#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))
#endif

#define TclGetInt4AtPtr(p) \
    (((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)))

/*
 * Macros used to compute the minimum and maximum of two integers. The ANSI C
 * "prototypes" for these macros are:
 *
 * int TclMin(int i, int j);
 * int TclMax(int i, int j);
 */

#define TclMin(i, j)	((((int) i) < ((int) j))? (i) : (j))
#define TclMax(i, j)	((((int) i) > ((int) j))? (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);
 */







|



|
|
|
|




|
|
|
|


|


|
|


|
|







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

#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)))
#endif

#define TclGetInt4AtPtr(p) \
    ((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))))

/*
 * Macros used to compute the minimum and maximum of two values. The ANSI C
 * "prototypes" for these macros are:
 *
 * size_t TclMin(size_t i, size_t j);
 * size_t TclMax(size_t i, size_t 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);
 */
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
    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);
 * static void		PushStringLiteral(CompileEnv *envPtr,
 *			    const char *string);
 */

#define PushLiteral(envPtr, string, length) \
    TclEmitPush(TclRegisterLiteral(envPtr, string, length, 0), (envPtr))
#define PushStringLiteral(envPtr, string) \
    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);
 */







|





|

|







1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
    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, Tcl_Size length);
 * static void		PushStringLiteral(CompileEnv *envPtr,
 *			    const char *string);
 */

#define PushLiteral(envPtr, string, length) \
    TclEmitPush(TclRegisterLiteral((envPtr), (string), (length), 0), (envPtr))
#define PushStringLiteral(envPtr, string) \
    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
/*
 * 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);
 */

#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))
#define ExceptionRangeTarget(envPtr, index, targetType) \
    ((envPtr)->exceptArrayPtr[(index)].targetType = CurrentOffset(envPtr))

/*
 * Check if there is an LVT for compiled locals
 */








|
|
|










|







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
/*
 * 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, 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) - (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
 * 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

#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);						\







|







1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
 * change during the course of the function.
 *
 * Macro to encapsulate the variable definition and setup.
 */

#define DefineLineInformation \
    ExtCmdLoc *mapPtr = envPtr->extCmdMapPtr;				\
    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
/*
 * 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. */







/*
 * 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







>
>
>
>
>
>







1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
/*
 * 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
#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);

#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







|







1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
#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,
			    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
#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);

#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");			\
    }

#define TclDTraceDbgMsg(p, m, ...) \
    do {								\
	if (tclDTraceDebugEnabled) {					\







|







|







1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
#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, 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];						\
	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) {					\
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
#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)
#define TCL_DTRACE_PROC_RETURN(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)
#define TCL_DTRACE_CMD_RETURN(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, \
		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) \







|



















|









|







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
#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 %" TCL_SIZE_MODIFIER "d %p", a0, a1, a2)
#define TCL_DTRACE_PROC_RETURN(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 %" TCL_SIZE_MODIFIER "d %p", a0, a1, a2)
#define TCL_DTRACE_CMD_RETURN(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 %" 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
/*
 * 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 <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|







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 © 2002 Andreas Kupries <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

/*
 *----------------------------------------------------------------------
 *
 * QueryConfigObjCmd --
 *
 *	Implementation of "::<package>::pkgconfig", the command to query
 *	configuration information embedded into a binary library.
 *
 * Results:
 *	A standard tcl result.
 *
 * Side effects:
 *	See the manual for what this command does.
 *
 *----------------------------------------------------------------------
 */

static int
QueryConfigObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    struct Tcl_Obj *const *objv)
{
    QCCD *cdPtr = (QCCD *)clientData;
    Tcl_Obj *pkgName = cdPtr->pkg;
    Tcl_Obj *pDB, *pkgDict, *val, *listPtr;
    size_t n = 0;
    int index, m;
    static const char *const subcmdStrings[] = {
	"get", "list", NULL
    };
    enum subcmds {
	CFG_GET, CFG_LIST
    };
    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;







|


|









|


|




|
<





|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
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 library.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the manual for what this command does.
 *
 *----------------------------------------------------------------------
 */

static int
QueryConfigObjCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    QCCD *cdPtr = (QCCD *)clientData;
    Tcl_Obj *pkgName = cdPtr->pkg;
    Tcl_Obj *pDB, *pkgDict, *val, *listPtr;
    Tcl_Size m, n = 0;

    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
	/*
	 * 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);
	return TCL_ERROR;
    }

    switch ((enum subcmds) 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);
	    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 = 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);
	    return TCL_ERROR;
	}

	if (m) {
	    Tcl_DictSearch s;
	    Tcl_Obj *key;
	    int done;







|



|










|













|
>
>
>


















|







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
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), (void *)NULL);
	return TCL_ERROR;
    }

    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]), (void *)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 *) 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", (void *)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
 *	Deallocates all non-transient memory allocated by Tcl_RegisterConfig.
 *
 *-------------------------------------------------------------------------
 */

static void
QueryConfigDelete(
    ClientData clientData)
{
    QCCD *cdPtr = (QCCD *)clientData;
    Tcl_Obj *pkgName = cdPtr->pkg;
    Tcl_Obj *pDB = GetConfigDict(cdPtr->interp);

    Tcl_DictObjRemove(NULL, pDB, pkgName);
    Tcl_DecrRefCount(pkgName);







|







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(
    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
 *	The package metadata database is freed.
 *
 *----------------------------------------------------------------------
 */

static void
ConfigDictDeleteProc(
    ClientData 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:
 */







|












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(
    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
/*
 * tclDTrace.d --
 *
 *	Tcl DTrace provider.
 *
 * Copyright (c) 2007-2008 Daniel A. Steffen <[email protected]>
 *
 * 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;



/*
 * 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)
     *		arg2: array of proc argument objects	(Tcl_Obj**)
     */
    probe proc__entry(const char *name, int 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);












>
>











|


|







1
2
3
4
5
6
7
8
9
10
11
12
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 <[email protected]>
 *
 * 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		(Tcl_Size)
     *		arg2: array of proc argument objects	(Tcl_Obj**)
     */
    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
     *	    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)
     *		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 *class);

    /***************************** cmd probes ******************************/
    /*
     *	tcl*:::cmd-entry probe
     *	    triggered immediately before commmand execution
     *		arg0: command name			(string)
     *		arg1: number of arguments		(int)
     *		arg2: array of command argument objects	(Tcl_Obj**)
     */
    probe cmd__entry(const char *name, int 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);







|




|







|


|







60
61
62
63
64
65
66
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			(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, 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		(Tcl_Size)
     *		arg2: array of command argument objects	(Tcl_Obj**)
     */
    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
     *		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 *class);

    /***************************** inst probes *****************************/
    /*
     *	tcl*:::inst-start probe
     *	    triggered immediately before execution of a bytecode
     *		arg0: bytecode name			(string)
     *		arg1: depth of stack			(int)
     *		arg2: top of stack			(Tcl_Obj**)
     */
    probe inst__start(const char *name, int 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)
     *		arg2: top of stack			(Tcl_Obj**)
     */
    probe inst__done(const char *name, int 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*)
     */







|







|


|




|


|







119
120
121
122
123
124
125
126
127
128
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, 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			(Tcl_Size)
     *		arg2: top of stack			(Tcl_Obj**)
     */
    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			(Tcl_Size)
     *		arg2: top of stack			(Tcl_Obj**)
     */
    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

typedef struct Tcl_ObjType {
    const char *name;
    void *freeIntRepProc;
    void *dupIntRepProc;
    void *updateStringProc;
    void *setFromAnyProc;









} Tcl_ObjType;

struct Tcl_Obj {
    size_t refCount;
    char *bytes;
    size_t length;
    const Tcl_ObjType *typePtr;
    union {
	long longValue;
	double doubleValue;
	void *otherValuePtr;
	int64_t wideValue;
	struct {







>
>
>
>
>
>
>
>
>



|

|







176
177
178
179
180
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 {
    Tcl_Size refCount;
    char *bytes;
    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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188

189
190





191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212








213
214

215



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242




243
244
245
246
247
248
249
250
251
252
253
254


255
256
257


258
259

260

261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
/* A Bison parser, made by GNU Bison 3.1.  */

/* Bison implementation for Yacc-like parsers in C

   Copyright (C) 1984, 1989-1990, 2000-2015, 2018 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/>.  */

/* 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.  */





/* 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

/* Bison version.  */
#define YYBISON_VERSION "3.1"

/* Skeleton name.  */
#define YYSKELETON_NAME "yacc.c"

/* Pure parsers.  */
#define YYPURE 1

/* Push parsers.  */
#define YYPUSH 0

/* Pull parsers.  */
#define YYPULL 1


/* 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.  */


/*
 * 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.

 *
 * 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 {
    MERam, MERpm, MER24
} MERIDIAN;


/*
 * yyparse will accept a 'struct DateInfo' as its parameter; that's where the
 * parsed fields will be returned.
 */

typedef struct DateInfo {

    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))






/*
 * An entry in the lexical lookup table.
 */

typedef struct _TABLE {
    const char *name;
    int type;
    time_t value;
} TABLE;

/*
 * Daylight-savings mode: on, off, or not yet known.
 */

typedef enum _DSTMODE {
    DSTon, DSToff, DSTmaybe
} DSTMODE;












# ifndef YY_NULLPTR
#  if defined __cplusplus && 201103L <= __cplusplus

#   define YY_NULLPTR nullptr



#  else
#   define YY_NULLPTR 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.  */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
  enum yytokentype
  {




    tAGO = 258,
    tDAY = 259,
    tDAYZONE = 260,
    tID = 261,
    tMERIDIAN = 262,
    tMONTH = 263,
    tMONTH_UNIT = 264,
    tSTARDATE = 265,
    tSEC_UNIT = 266,
    tSNUMBER = 267,
    tUNUMBER = 268,
    tZONE = 269,


    tEPOCH = 270,
    tDST = 271,
    tISOBASE = 272,


    tDAY_UNIT = 273,
    tNEXT = 274

  };

#endif

/* Value type.  */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED

union YYSTYPE
{


    time_t 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);































































/* Copy the second part of user declarations.  */




/*
 * Prototypes of internal functions.
 */

static int		LookupWord(YYSTYPE* yylvalPtr, char *buff);
 static void		TclDateerror(YYLTYPE* location,
				     DateInfo* info, const char *s);
 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




#ifdef YYTYPE_UINT8
typedef YYTYPE_UINT8 yytype_uint8;




#else
typedef unsigned char yytype_uint8;
#endif





#ifdef YYTYPE_INT8



typedef YYTYPE_INT8 yytype_int8;
#else
typedef signed char yytype_int8;
#endif

#ifdef YYTYPE_UINT16


typedef YYTYPE_UINT16 yytype_uint16;
#else
typedef unsigned short yytype_uint16;
#endif






#ifdef YYTYPE_INT16





typedef YYTYPE_INT16 yytype_int16;







#else
typedef short yytype_int16;
#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
#  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)














#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
# if (defined __GNUC__                                               \
      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
# else
#  define YY_ATTRIBUTE(Spec) /* empty */
# 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 _Noreturn \
     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
# if defined _MSC_VER && 1200 <= _MSC_VER
#  define _Noreturn __declspec (noreturn)
# else
#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
# endif
#endif

/* Suppress unused-variable warnings by "using" E.  */
#if ! defined lint || defined __GNUC__
# define YYUSE(E) ((void) (E))
#else
# define YYUSE(E) /* empty */
#endif

#if defined __GNUC__ && ! defined __ICC && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
/* Suppress an incorrect diagnostic about yylval being uninitialized.  */


# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
    _Pragma ("GCC diagnostic push") \
    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\




    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")

# 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 yyoverflow || YYERROR_VERBOSE

/* 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
|



|
>












|

















>
>
>
>







|
|

|
|



















<

<
|
<







|
|
>
















<
<
<
|
|
<
<
>






<
|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<











|
>
|
|
>
>
>
>
>





|


|












|
>
>
>
>
>
>
>
>

|
>
|
>
>
>

|



<
<
<
<
<
<
<
<









|




>
>
>
>
|
|
|
|
|
|
|
|
|
<
|
|
>
>
|
|
|
>
>
|
|
>

>




<



<
|




<





















>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>







|

|

<
<









>
>
>
|
|
>
>
>
>
|
<


>
>
>
>
|
>
>
>
|




|
>
>
|

|


>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>

|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|







|
>
>
>
>
>
>
>
>
>
>
>
>
>













>
|
<
|
<
|

|

<
<
<
<



<
<
|
<
<
<
|

|





|

|


<

>
>
|
|
|
>
>
>
>

>
|












>
>
>
>
>
>
>
>
>
>
>

>
>
>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

72

73

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99



100
101


102
103
104
105
106
107
108

109


110


































111
112
113

























114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175








176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

221
222
223

224
225
226
227
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
/* 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-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 <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, and Bison version.  */
#define YYBISON 30802

/* Bison version string.  */
#define YYBISON_VERSION "3.8.2"

/* Skeleton name.  */
#define YYSKELETON_NAME "yacc.c"

/* Pure parsers.  */
#define YYPURE 1

/* Push parsers.  */
#define YYPUSH 0

/* Pull parsers.  */
#define YYPULL 1


/* Substitute the variable and function names.  */
#define yyparse         TclDateparse
#define yylex           TclDatelex
#define yyerror         TclDateerror
#define yydebug         TclDatedebug



/* 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 © 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 */




#if 0
#define YYDEBUG 1


#endif

/*
 * yyparse will accept a 'struct DateInfo' as its parameter; that's where the
 * parsed fields will be returned.
 */


#include "tclDate.h"





































#define YYMALLOC	Tcl_Alloc
#define YYFREE(x)	(Tcl_Free((void*) (x)))


























#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)		((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 {
    const char *name;
    int type;
    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
#   if 201103L <= __cplusplus
#    define YY_NULLPTR nullptr
#   else
#    define YY_NULLPTR 0
#   endif
#  else
#   define YY_NULLPTR ((void*)0)
#  endif
# endif










/* Debug traces.  */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int TclDatedebug;
#endif

/* Token kinds.  */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
  enum yytokentype
  {
    YYEMPTY = -2,
    YYEOF = 0,                     /* "end of file"  */
    YYerror = 256,                 /* error  */
    YYUNDEF = 257,                 /* "invalid token"  */
    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  */

    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
{


    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;


/* Second part of user prologue.  */


/*
 * Prototypes of internal functions.
 */

static int		LookupWord(YYSTYPE* yylvalPtr, char *buff);
static void		TclDateerror(YYLTYPE* location,
				     DateInfo* info, const char *s);
static int		TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
				   DateInfo* info);


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.  */

#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

#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 __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 __INT_LEAST16_MAX__
typedef __INT_LEAST16_TYPE__ yytype_int16;
#elif defined YY_STDINT_H
typedef int_least16_t yytype_int16;
#else
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 __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_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 __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                                  \
  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_PURE

# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__)

#  define YY_ATTRIBUTE_PURE __attribute__ ((__pure__))
# else
#  define YY_ATTRIBUTE_PURE
# endif




#endif

#ifndef YY_ATTRIBUTE_UNUSED


# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__)



#  define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__))
# else
#  define YY_ATTRIBUTE_UNUSED
# endif
#endif

/* Suppress unused-variable warnings by "using" E.  */
#if ! defined lint || defined __GNUC__
# define YY_USE(E) ((void) (E))
#else
# define YY_USE(E) /* empty */
#endif


/* 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\"")
# 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      \
    _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

/* 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
#  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 */


#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;
  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)

/* The size of an array large to enough to hold all stacks, each with
   N elements.  */
# define YYSTACK_BYTES(N) \

     ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (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;                                            \
        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
        Stack = &yyptr->Stack_alloc;                                    \
        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
        yyptr += yynewbytes / sizeof (*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)))
#  else
#   define YYCOPY(Dst, Src, Count)              \
      do                                        \
        {                                       \
          YYSIZE_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

/* YYNTOKENS -- Number of terminals.  */
#define YYNTOKENS  26
/* YYNNTS -- Number of nonterminals.  */
#define YYNNTS  16
/* YYNRULES -- Number of rules.  */
#define YYNRULES  56
/* YYNSTATES -- Number of states.  */
#define YYNSTATES  85

/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
   by yylex, with out-of-bounds checking.  */
#define YYUNDEFTOK  2
#define YYMAXUTOK   274




#define YYTRANSLATE(YYX)                                                \

  ((unsigned) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)


/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
   as returned by yylex, without out-of-bounds checking.  */
static const yytype_uint8 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,     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,     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
};

#if YYDEBUG
  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
static const yytype_uint16 yyrline[] =
{

       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
};
#endif




#if YYDEBUG || YYERROR_VERBOSE || 0




/* 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
};
#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[] =

{
       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

#define YYPACT_NINF -18

#define yypact_value_is_default(Yystate) \
  (!!((Yystate) == (-18)))

#define YYTABLE_NINF -1

#define yytable_value_is_error(Yytable_value) \
  0

  /* 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
};

  /* 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[] =
{
       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

};

  /* YYPGOTO[NTERM-NUM].  */
static const yytype_int8 yypgoto[] =
{
     -18,   -18,   -18,   -18,   -18,   -18,   -18,   -18,   -18,   -18,


     -18,   -18,   -18,    -9,   -18,     7
};

  /* YYDEFGOTO[NTERM-NUM].  */
static const yytype_int8 yydefgoto[] =
{
      -1,     1,    17,    18,    19,    20,    21,    22,    23,    24,

      25,    26,    27,    28,    29,    66
};

  /* 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[] =
{

      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,
       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
};

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
};

  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
     symbol of state STATE-NUM.  */
static const yytype_uint8 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,
      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
};

  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
static const yytype_uint8 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




};

  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
static const yytype_uint8 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

};




#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 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)


/* Error token number */
#define YYTERROR        1
#define YYERRCODE       256


/* 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)                                \







<
|









|





|




>
|












|


|
|











|




|











|


|

|

|

|

<
<
|
|

>
>
>
|
>
|
>


|
|





|
|


|


















|



|
|

>
|
>
|
|
|
|
|



>
>
>
|
>
>
>
>




|
|
|
|
|
>
|
|

<

<
<
<
|
>

<
<
<
<
>
>
|

|

|
|

|

|


|
|


|
|
|
|
|
|
|
|
>
>
|


|
|
|
|

|
|
>
|
|
|
|
|
|
|
>


|


<
>
>
|


|


|
>
|


|
|
|
|

>
|
|
|
|
|
<
>
|
|
|


|

>
|
|
>
|
|
|
<
|
|
|


|
|
|

|
|
|
>
|
|
|
|
|
>
|


|
|

<
<
|
|
|
|
>
>
>
>


|
|


|
>
|
|
|
|
>


>
>



<
<




>




|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

>
|
<
|
<







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
#  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 */

#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
{
  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 (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) \
             + 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                                                                  \
      {                                                                 \
        YYPTRDIFF_T yynewbytes;                                         \
        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
        Stack = &yyptr->Stack_alloc;                                    \
        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, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src)))
#  else
#   define YYCOPY(Dst, Src, Count)              \
      do                                        \
        {                                       \
          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   98

/* YYNTOKENS -- Number of terminals.  */
#define YYNTOKENS  31
/* YYNNTS -- Number of nonterminals.  */
#define YYNNTS  23
/* YYNRULES -- Number of rules.  */
#define YYNRULES  72
/* YYNSTATES -- Number of states.  */
#define YYNSTATES  103



/* 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)                                \
  (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.  */
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,    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,    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,    20,    21,    22,    23
};

#if YYDEBUG
/* 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,
     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 || 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 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
};





static const char *
yysymbol_name (yysymbol_kind_t yysymbol)
{




  return yytname[yysymbol];
}
#endif

#define YYPACT_NINF (-21)

#define yypact_value_is_default(Yyn) \
  ((Yyn) == YYPACT_NINF)

#define YYTABLE_NINF (-68)

#define yytable_value_is_error(Yyn) \
  0

/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
   STATE-NUM.  */
static const yytype_int8 yypact[] =
{
     -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_int8 yydefact[] =
{
       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].  */
static const yytype_int8 yypgoto[] =
{

     -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].  */
static const yytype_int8 yydefgoto[] =
{
       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_int8 yytable[] =
{
      59,    44,     6,    41,     8,    38,    52,    53,    63,    42,
      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,

      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_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 symbol kind of the accessing symbol of
   state STATE-NUM.  */
static const yytype_int8 yystos[] =
{
       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,
      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[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM.  */
static const yytype_int8 yyr1[] =
{


       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[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,     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 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)

/* Backward compatibility with an undocumented macro.
   Use YYerror or YYUNDEF. */

#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
# define YYDPRINTF(Args)                        \
do {                                            \
  if (yydebug)                                  \
    YYFPRINTF Args;                             \
} while (0)


/* YY_LOCATION_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 YY_LOCATION_PRINT





# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL

/* Print *YYLOCP on YYO.  Private, do not rely on its existence. */

YY_ATTRIBUTE_UNUSED
static unsigned
yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
{
  unsigned 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))




# else

#  define YY_LOCATION_PRINT(File, Loc) ((void) 0)



# endif
#endif



# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
do {                                                                      \
  if (yydebug)                                                            \
    {                                                                     \
      YYFPRINTF (stderr, "%s ", Title);                                   \
      yy_symbol_print (stderr,                                            \
                  Type, Value, Location, info); \
      YYFPRINTF (stderr, "\n");                                           \
    }                                                                     \
} while (0)


/*----------------------------------------.
| Print this symbol's value on YYOUTPUT.  |
`----------------------------------------*/

static void

yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
{
  FILE *yyo = yyoutput;
  YYUSE (yyo);
  YYUSE (yylocationp);
  YYUSE (info);
  if (!yyvaluep)
    return;
# ifdef YYPRINT
  if (yytype < YYNTOKENS)
    YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
# endif
  YYUSE (yytype);

}


/*--------------------------------.
| Print this symbol on YYOUTPUT.  |
`--------------------------------*/

static void

yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
{
  YYFPRINTF (yyoutput, "%s %s (",
             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);

  YY_LOCATION_PRINT (yyoutput, *yylocationp);
  YYFPRINTF (yyoutput, ": ");
  yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, info);
  YYFPRINTF (yyoutput, ")");
}

/*------------------------------------------------------------------.
| 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)
{
  YYFPRINTF (stderr, "Stack now");
  for (; yybottom <= yytop; yybottom++)
    {
      int yybot = *yybottom;
      YYFPRINTF (stderr, " %d", yybot);
    }







|



>
>
|
>
>
>
>
>
|




|


|



















|

|
|
>
>
>

|
>
|
>
>
>
|
|
>


|





|





|
|
|


>
|

|
|
|
|


<
|
<
<
|
>



|
|
|


>
|

|
|

|
|
|
|








|







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
# define YYDPRINTF(Args)                        \
do {                                            \
  if (yydebug)                                  \
    YYFPRINTF Args;                             \
} while (0)


/* 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

#  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 int
yy_location_print_ (FILE *yyo, YYLTYPE const * const yylocp)
{
  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 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 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, Kind, Value, Location)                    \
do {                                                                      \
  if (yydebug)                                                            \
    {                                                                     \
      YYFPRINTF (stderr, "%s ", Title);                                   \
      yy_symbol_print (stderr,                                            \
                  Kind, Value, Location, info); \
      YYFPRINTF (stderr, "\n");                                           \
    }                                                                     \
} while (0)


/*-----------------------------------.
| Print this symbol's value on YYO.  |
`-----------------------------------*/

static void
yy_symbol_value_print (FILE *yyo,
                       yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
{
  FILE *yyoutput = yyo;
  YY_USE (yyoutput);
  YY_USE (yylocationp);
  YY_USE (info);
  if (!yyvaluep)
    return;

  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN


  YY_USE (yykind);
  YY_IGNORE_MAYBE_UNINITIALIZED_END
}


/*---------------------------.
| Print this symbol on YYO.  |
`---------------------------*/

static void
yy_symbol_print (FILE *yyo,
                 yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, DateInfo* info)
{
  YYFPRINTF (yyo, "%s %s (",
             yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind));

  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 (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


/*------------------------------------------------.
| 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)

{
  unsigned long yylno = yyrline[yyrule];
  int yynrhs = yyr2[yyrule];
  int yyi;
  YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\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);
      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 YY_STACK_PRINT(Bottom, Top)
# define YY_REDUCE_PRINT(Rule)
#endif /* !YYDEBUG */


/* YYINITDEPTH -- initial size of the parser's stacks.  */
#ifndef YYINITDEPTH







|
>

|


|






|
|
|














|
|







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


/*------------------------------------------------.
| Report that the YYRULE is going to be reduced.  |
`------------------------------------------------*/

static void
yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, YYLTYPE *yylsp,
                 int yyrule, DateInfo* info)
{
  int yylno = yyrline[yyrule];
  int yynrhs = yyr2[yyrule];
  int yyi;
  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,
                       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) ((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
   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)

{
  YYUSE (yyvaluep);
  YYUSE (yylocationp);
  YYUSE (info);
  if (!yymsg)
    yymsg = "Deleting";
  YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);

  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
  YYUSE (yytype);
  YY_IGNORE_MAYBE_UNINITIALIZED_END
}






/*----------.
| yyparse.  |
`----------*/

int
yyparse (DateInfo* info)
{
/* The lookahead symbol.  */
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 yystate;
    /* Number of tokens to shift before error messages enabled.  */
    int yyerrstatus;

    /* 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
       to reallocate them elsewhere.  */




    /* The state stack.  */
    yytype_int16 yyssa[YYINITDEPTH];
    yytype_int16 *yyss;
    yytype_int16 *yyssp;

    /* The semantic value stack.  */
    YYSTYPE yyvsa[YYINITDEPTH];
    YYSTYPE *yyvs;
    YYSTYPE *yyvsp;

    /* The location stack.  */
    YYLTYPE yylsa[YYINITDEPTH];
    YYLTYPE *yyls;
    YYLTYPE *yylsp;

    /* The locations where the error started and ended.  */
    YYLTYPE yyerror_range[3];

    YYSIZE_T yystacksize;

  int yyn;

  int yyresult;
  /* Lookahead token as an internal (translated) token number.  */
  int yytoken = 0;
  /* The variables used to return semantic value and location from the
     action routines.  */
  YYSTYPE yyval;
  YYLTYPE yyloc;

#if YYERROR_VERBOSE
  /* Buffer for error messages, and its allocated size.  */
  char yymsgbuf[128];
  char *yymsg = yymsgbuf;
  YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
#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:
  /* 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:



  *yyssp = yystate;



  if (yyss + yystacksize - 1 <= yyssp)



    {
      /* Get the current used size of the three stacks, in elements.  */
      YYSIZE_T yysize = yyssp - yyss + 1;

#ifdef 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.  */

        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),
                    &yystacksize);

        yyls = yyls1;
        yyss = yyss1;
        yyvs = yyvs1;

      }
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
      goto yyexhaustedlab;
# else
      /* Extend the stack our own way.  */
      if (YYMAXDEPTH <= yystacksize)
        goto yyexhaustedlab;

      yystacksize *= 2;
      if (YYMAXDEPTH < yystacksize)
        yystacksize = YYMAXDEPTH;

      {
        yytype_int16 *yyss1 = yyss;
        union yyalloc *yyptr =
          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));

        if (! yyptr)
          goto yyexhaustedlab;

        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;


      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
                  (unsigned long) yystacksize));


      if (yyss + yystacksize - 1 <= yyssp)
        YYABORT;
    }


  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.  */
  if (yychar == YYEMPTY)
    {
      YYDPRINTF ((stderr, "Reading a token: "));
      yychar = yylex (&yylval, &yylloc, info);
    }

  if (yychar <= YYEOF)
    {
      yychar = yytoken = YYEOF;

      YYDPRINTF ((stderr, "Now at end of input.\n"));











    }
  else
    {
      yytoken = YYTRANSLATE (yychar);
      YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
    }








<

<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






|
>

|
|
|


|


|


>
>











|

















<
<
<
|

|

<
<
<
<
<
|


>
>
>
|
|
|
|

|

|
|

|

|
|

<
<
<
<
<

>

|
|





|
<
|
|
|
<







<
<
<
<
<


<
<
<

>



>

|

|




>
>
>
>
|
>
>
>
|
>
>


>
>
>


|

|




>

<







|
|
|

<
<


>

<
|
<
<


<
>





|

|
>

<
>








<





>
|
|
>




>

<





>





<










|


|





|
>

>
>
>
>
>
>
>
>
>
>
>







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
   evaluated with infinite-precision integer arithmetic.  */

#ifndef YYMAXDEPTH
# define YYMAXDEPTH 10000
#endif

































































































































































































































/*-----------------------------------------------.
| Release the memory associated to this symbol.  |
`-----------------------------------------------*/

static void
yydestruct (const char *yymsg,
            yysymbol_kind_t yykind, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, DateInfo* info)
{
  YY_USE (yyvaluep);
  YY_USE (yylocationp);
  YY_USE (info);
  if (!yymsg)
    yymsg = "Deleting";
  YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp);

  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
  YY_USE (yykind);
  YY_IGNORE_MAYBE_UNINITIALIZED_END
}






/*----------.
| yyparse.  |
`----------*/

int
yyparse (DateInfo* info)
{
/* 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;




    yy_state_fast_t yystate = 0;
    /* Number of tokens to shift before error messages enabled.  */
    int yyerrstatus = 0;






    /* Refer to the stacks through separate pointers, to allow yyoverflow
       to reallocate them elsewhere.  */

    /* Their size.  */
    YYPTRDIFF_T yystacksize = YYINITDEPTH;

    /* 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: array, bottom, top.  */
    YYSTYPE yyvsa[YYINITDEPTH];
    YYSTYPE *yyvs = yyvsa;
    YYSTYPE *yyvsp = yyvs;

    /* The location stack: array, bottom, top.  */
    YYLTYPE yylsa[YYINITDEPTH];
    YYLTYPE *yyls = yylsa;
    YYLTYPE *yylsp = yyls;






  int yyn;
  /* The return value of yyparse.  */
  int yyresult;
  /* 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;

  /* The locations where the error started and ended.  */

  YYLTYPE yyerror_range[3];




#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;






  YYDPRINTF ((stderr, "Starting parse\n"));




  yychar = YYEMPTY; /* Cause a token to be read.  */

  yylsp[0] = yylloc;
  goto yysetstate;


/*------------------------------------------------------------.
| yynewstate -- push a new state, which is found in yystate.  |
`------------------------------------------------------------*/
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:
  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.  */
      YYPTRDIFF_T yysize = yyssp - yyss + 1;

# 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;

        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 * YYSIZEOF (*yyssp),
                    &yyvs1, yysize * YYSIZEOF (*yyvsp),
                    &yyls1, yysize * YYSIZEOF (*yylsp),
                    &yystacksize);


        yyss = yyss1;
        yyvs = yyvs1;
        yyls = yyls1;
      }

# else /* defined YYSTACK_RELOCATE */


      /* Extend the stack our own way.  */
      if (YYMAXDEPTH <= yystacksize)

        YYNOMEM;
      yystacksize *= 2;
      if (YYMAXDEPTH < yystacksize)
        yystacksize = YYMAXDEPTH;

      {
        yy_state_t *yyss1 = yyss;
        union yyalloc *yyptr =
          YY_CAST (union yyalloc *,
                   YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize))));
        if (! yyptr)

          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


      yyssp = yyss + yysize - 1;
      yyvsp = yyvs + yysize - 1;
      yylsp = yyls + yysize - 1;

      YY_IGNORE_USELESS_CAST_BEGIN
      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 */



  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 empty, or end-of-input, or a valid lookahead.  */
  if (yychar == YYEMPTY)
    {
      YYDPRINTF ((stderr, "Reading a token\n"));
      yychar = yylex (&yylval, &yylloc, info);
    }

  if (yychar <= 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
  /* 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;



  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:
  /* 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'.







<
<
<
<





>
>
>














|







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
  /* 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);




  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:
  /* 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

  /* Default location. */
  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
  yyerror_range[1] = yyloc;
  YY_REDUCE_PRINT (yyn);
  switch (yyn)
    {
        case 4:

    {
	    yyHaveTime++;
	}

    break;

  case 5:

    {
	    yyHaveZone++;
	}

    break;

  case 6:

    {
	    yyHaveDate++;
	}

    break;

  case 7:

    {
	    yyHaveOrdinalMonth++;

	}

    break;

  case 8:




    {





	    yyHaveDay++;
	}




    break;

  case 9:

    {
	    yyHaveRel++;


	}

    break;

  case 10:

    {
	    yyHaveTime++;

	    yyHaveDate++;
	}

    break;

  case 11:

    {
	    yyHaveTime++;
	    yyHaveDate++;
	    yyHaveRel++;
	}

    break;

  case 13:

    {
	    yyHour = (yyvsp[-1].Number);
	    yyMinutes = 0;
	    yySeconds = 0;
	    yyMeridian = (yyvsp[0].Meridian);
	}

    break;

  case 14:

    {
	    yyHour = (yyvsp[-3].Number);
	    yyMinutes = (yyvsp[-1].Number);
	    yySeconds = 0;
	    yyMeridian = (yyvsp[0].Meridian);
	}

    break;

  case 15:

    {
	    yyHour = (yyvsp[-5].Number);
	    yyMinutes = (yyvsp[-3].Number);
	    yySeconds = (yyvsp[-1].Number);
	    yyMeridian = (yyvsp[0].Meridian);
	}

    break;

  case 16:





    {


	    yyTimezone = (yyvsp[-1].Number);
	    if (yyTimezone > HOUR( 12)) yyTimezone -= HOUR(100);
	    yyDSTmode = DSTon;
	}

    break;

  case 17:

    {
	    yyTimezone = (yyvsp[0].Number);
	    if (yyTimezone > HOUR( 12)) yyTimezone -= HOUR(100);
	    yyDSTmode = DSToff;
	}

    break;

  case 18:

    {
	    yyTimezone = (yyvsp[0].Number);
	    yyDSTmode = DSTon;
	}

    break;

  case 19:

    {
	    yyTimezone = -(yyvsp[-1].Number)*((yyvsp[0].Number) % 100 + ((yyvsp[0].Number) / 100) * 60);
	    yyDSTmode = DSToff;
	}

    break;

  case 20:

    {
	    yyDayOrdinal = 1;
	    yyDayNumber = (yyvsp[0].Number);
	}

    break;

  case 21:

    {
	    yyDayOrdinal = 1;
	    yyDayNumber = (yyvsp[-1].Number);
	}

    break;

  case 22:

    {
	    yyDayOrdinal = (yyvsp[-1].Number);
	    yyDayNumber = (yyvsp[0].Number);
	}







    break;

  case 23:

    {
	    yyDayOrdinal = (yyvsp[-2].Number) * (yyvsp[-1].Number);
	    yyDayNumber = (yyvsp[0].Number);
	}

    break;

  case 24:

    {
	    yyDayOrdinal = 2;
	    yyDayNumber = (yyvsp[0].Number);
	}








    break;

  case 25:

    {
	    yyMonth = (yyvsp[-2].Number);
	    yyDay = (yyvsp[0].Number);
	}

    break;

  case 26:

    {
	    yyMonth = (yyvsp[-4].Number);
	    yyDay = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;

  case 27:

    {
	    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:

    {
	    yyMonth = (yyvsp[-1].Number);
	    yyDay = (yyvsp[0].Number);
	}

    break;

  case 31:

    {
	    yyMonth = (yyvsp[-3].Number);
	    yyDay = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;

  case 32:

    {
	    yyMonth = (yyvsp[0].Number);
	    yyDay = (yyvsp[-1].Number);
	}

    break;

  case 33:

    {
	    yyMonth = 1;
	    yyDay = 1;
	    yyYear = EPOCH;
	}

    break;

  case 34:

    {
	    yyMonth = (yyvsp[-1].Number);
	    yyDay = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;

  case 35:

    {
	    yyMonthOrdinal = 1;
	    yyMonth = (yyvsp[0].Number);
	}

    break;

  case 36:

    {
	    yyMonthOrdinal = (yyvsp[-1].Number);
	    yyMonth = (yyvsp[0].Number);
	}

    break;

  case 37:


    {
	    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);
	}

    break;

  case 38:

    {
	    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:

    {
	    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);
	}

    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 41:

    {
	    /*
	     * 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;
	}

    break;

  case 42:

    {
	    yyRelSeconds *= -1;
	    yyRelMonth *= -1;
	    yyRelDay *= -1;
	}

    break;

  case 44:

    {
	    *yyRelPointer += (yyvsp[-2].Number) * (yyvsp[-1].Number) * (yyvsp[0].Number);
	}

    break;

  case 45:

    {
	    *yyRelPointer += (yyvsp[-1].Number) * (yyvsp[0].Number);
	}

    break;

  case 46:

    {
	    *yyRelPointer += (yyvsp[0].Number);
	}

    break;

  case 47:

    {
	    *yyRelPointer += (yyvsp[-1].Number) * (yyvsp[0].Number);


	}




    break;

  case 48:

    {
	    *yyRelPointer += (yyvsp[0].Number);
	}

    break;

  case 49:

    {
	    (yyval.Number) = -1;
	}

    break;

  case 50:

    {
	    (yyval.Number) =  1;
	}

    break;

  case 51:

    {
	    (yyval.Number) = (yyvsp[0].Number);
	    yyRelPointer = &yyRelSeconds;
	}

    break;

  case 52:

    {
	    (yyval.Number) = (yyvsp[0].Number);
	    yyRelPointer = &yyRelDay;
	}

    break;

  case 53:

    {
	    (yyval.Number) = (yyvsp[0].Number);
	    yyRelPointer = &yyRelMonth;
	}






    break;

  case 54:




    {





	    if (yyHaveTime && yyHaveDate && !yyHaveRel) {



		yyYear = (yyvsp[0].Number);
	    } else {
		yyHaveTime++;
		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:

    {
	    (yyval.Meridian) = MER24;
	}

    break;

  case 56:

    {
	    (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);

  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];

  yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
  if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
    yystate = yytable[yystate];
  else
    yystate = yydefgoto[yyn - YYNTOKENS];


  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);

  /* 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)
        {







|
|
<
|

<


|
|
<
|

<


|
|
<
|

<


|
|
<
<
>

<


|
|
>
>
>
|
>
>
>
>
>
<
|
>
|
>
>


<
|
|
<
>
>

<


<
|
|
|
>
|

<


|
|
<
|
|
|

<


|
|
<





<


|
|
<
<
<
<


<


|
|
<
<
<
|
|

<


|
|
>
>
>
>
|
>
>
|
<


<


|
|
<
|
<


<


|
|
<
|
|

<


|
|
<



<


|
|
<

|

<


|
|
<

|

<


|
|
<

|

>

>
>
>
>
>


|
|
<

|

<


<
|
|

|

>

>
>
>
>
>
>


<
|
|



<


<
|
|




<


<
|
|
<
<
<
<
<
<
<
<
<
<




<


<
<
<
<
<
<
<
<
<
<
|
|
<



<


<
|
|




<


|
|
<



<


|
|
<




<


<
|
|




<


<
|
|
|
|

<


<
|
|
|
|

<

<
<

>
|
<
|
|
|
>
>
|
>
>
|
>
|

<


<
|
|
<
<
<
<




<


<
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<







>

>
>
>
>
>
>
>
>
>
>


<
|
|









|

<


<
|
|




<


<
|
|
|

<


<
|
|
|

<


<
|
|
|

<


<
|
|
|
>
>
|
>
|
>
>


<
|
|


<


<
|
|


<


<
|
|


<


<
|
|



<


<
|
|



<


<
|
|



>

>
>
>
>


|
|
>
>
>
|
>
>
>
>
>
|
>
>
>


|











<


<
|
|


<


<
|
|


<

















|



<







|
|
|
<
|
|
<
|
>










|
<



<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<

<







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

  /* Default location. */
  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
  yyerror_range[1] = yyloc;
  YY_REDUCE_PRINT (yyn);
  switch (yyn)
    {
  case 4: /* item: time  */
               {

	    yyIncrFlags(CLF_TIME);
	}

    break;

  case 5: /* item: zone  */
               {

	    yyIncrFlags(CLF_ZONE);
	}

    break;

  case 6: /* item: date  */
               {

	    yyIncrFlags(CLF_HAVEDATE);
	}

    break;

  case 7: /* item: ordMonth  */
                   {


	    yyIncrFlags(CLF_ORDINALMONTH);
	}

    break;

  case 8: /* item: day  */
              {
	    yyIncrFlags(CLF_DAYOFWEEK);
	}
    break;

  case 9: /* item: relspec  */
                  {
	    info->flags |= CLF_RELCONV;
	}
    break;


  case 10: /* item: iso  */
              {
	    yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
	}
    break;


  case 11: /* item: trek  */
               {

	    yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
	    info->flags |= CLF_RELCONV;
	}

    break;


  case 13: /* iextime: tUNUMBER ':' tUNUMBER ':' tUNUMBER  */
                                             {
	    yyHour = (yyvsp[-4].Number);
	    yyMinutes = (yyvsp[-2].Number);
	    yySeconds = (yyvsp[0].Number);
	}

    break;

  case 14: /* iextime: tUNUMBER ':' tUNUMBER  */
                                {

	    yyHour = (yyvsp[-2].Number);
	    yyMinutes = (yyvsp[0].Number);
	    yySeconds = 0;
	}

    break;

  case 15: /* time: tUNUMBER tMERIDIAN  */
                             {

	    yyHour = (yyvsp[-1].Number);
	    yyMinutes = 0;
	    yySeconds = 0;
	    yyMeridian = (yyvsp[0].Meridian);
	}

    break;

  case 16: /* time: iextime o_merid  */
                          {




	    yyMeridian = (yyvsp[0].Meridian);
	}

    break;

  case 17: /* zone: tZONE tDST  */
                     {



	    yyTimezone = (yyvsp[-1].Number);
	    yyDSTmode = DSTon;
	}

    break;

  case 18: /* zone: tZONE  */
                {
	    yyTimezone = (yyvsp[0].Number);
	    yyDSTmode = DSToff;
	}
    break;

  case 19: /* zone: tDAYZONE  */
                   {
	    yyTimezone = (yyvsp[0].Number);

	    yyDSTmode = DSTon;
	}

    break;

  case 20: /* zone: tZONEwO4 sign INTNUM  */
                               { /* GMT+0100, GMT-1000, etc. */

	    yyTimezone = (yyvsp[-2].Number) - (yyvsp[-1].Number)*((yyvsp[0].Number) % 100 + ((yyvsp[0].Number) / 100) * 60);

	    yyDSTmode = DSToff;
	}

    break;

  case 21: /* zone: tZONEwO2 sign INTNUM  */
                               { /* GMT+1, GMT-10, etc. */

	    yyTimezone = (yyvsp[-2].Number) - (yyvsp[-1].Number)*((yyvsp[0].Number) * 60);
	    yyDSTmode = DSToff;
	}

    break;

  case 22: /* zone: sign INTNUM  */
                      { /* +0100, -0100 */

	    yyTimezone = -(yyvsp[-1].Number)*((yyvsp[0].Number) % 100 + ((yyvsp[0].Number) / 100) * 60);
	    yyDSTmode = DSToff;
	}

    break;

  case 25: /* day: tDAY  */
               {

	    yyDayOrdinal = 1;
	    yyDayOfWeek = (yyvsp[0].Number);
	}

    break;

  case 26: /* day: tDAY comma  */
                     {

	    yyDayOrdinal = 1;
	    yyDayOfWeek = (yyvsp[-1].Number);
	}

    break;

  case 27: /* day: tUNUMBER tDAY  */
                        {

	    yyDayOrdinal = (yyvsp[-1].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 29: /* day: sign tUNUMBER tDAY  */
                             {

	    yyDayOrdinal = (yyvsp[-2].Number) * (yyvsp[-1].Number);
	    yyDayOfWeek = (yyvsp[0].Number);
	}

    break;


  case 30: /* day: tNEXT tDAY  */
                     {
	    yyDayOrdinal = 2;
	    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 32: /* date: tUNUMBER '/' tUNUMBER  */
                                {
	    yyMonth = (yyvsp[-2].Number);
	    yyDay = (yyvsp[0].Number);
	}

    break;


  case 33: /* date: tUNUMBER '/' tUNUMBER '/' tUNUMBER  */
                                             {
	    yyMonth = (yyvsp[-4].Number);
	    yyDay = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;


  case 35: /* date: tUNUMBER '-' tMONTH '-' tUNUMBER  */
                                           {










	    yyDay = (yyvsp[-4].Number);
	    yyMonth = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;











  case 36: /* date: tMONTH tUNUMBER  */
                          {

	    yyMonth = (yyvsp[-1].Number);
	    yyDay = (yyvsp[0].Number);
	}

    break;


  case 37: /* date: tMONTH tUNUMBER comma tUNUMBER  */
                                         {
	    yyMonth = (yyvsp[-3].Number);
	    yyDay = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;

  case 38: /* date: tUNUMBER tMONTH  */
                          {

	    yyMonth = (yyvsp[0].Number);
	    yyDay = (yyvsp[-1].Number);
	}

    break;

  case 39: /* date: tEPOCH  */
                 {

	    yyMonth = 1;
	    yyDay = 1;
	    yyYear = EPOCH;
	}

    break;


  case 40: /* date: tUNUMBER tMONTH tUNUMBER  */
                                   {
	    yyMonth = (yyvsp[-1].Number);
	    yyDay = (yyvsp[-2].Number);
	    yyYear = (yyvsp[0].Number);
	}

    break;


  case 41: /* ordMonth: tNEXT tMONTH  */
                       {
	    yyMonthOrdinalIncr = 1;
	    yyMonthOrdinal = (yyvsp[0].Number);
	}

    break;


  case 42: /* ordMonth: tNEXT tUNUMBER tMONTH  */
                                {
	    yyMonthOrdinalIncr = (yyvsp[-1].Number);
	    yyMonthOrdinal = (yyvsp[0].Number);
	}

    break;



  case 45: /* isodate: tISOBAS8  */
                   { /* YYYYMMDD */

	    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 48: /* isotime: tISOBAS6  */
                   {




	    yyHour = (yyvsp[0].Number) / 10000;
	    yyMinutes = ((yyvsp[0].Number) % 10000)/100;
	    yySeconds = (yyvsp[0].Number) % 100;
	}

    break;


  case 51: /* iso: tISOBASL tISOBAS6  */









                            { /* YYYYMMDDhhmmss */





	    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 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) * (144LL * 60LL);
	}

    break;


  case 54: /* relspec: relunits tAGO  */
                        {
	    yyRelSeconds *= -1;
	    yyRelMonth *= -1;
	    yyRelDay *= -1;
	}

    break;


  case 56: /* relunits: sign SP INTNUM unit  */
                               {
	    *yyRelPointer += (yyvsp[-3].Number) * (yyvsp[-1].Number) * (yyvsp[0].Number);
	}

    break;


  case 57: /* relunits: sign INTNUM unit  */
                           {
	    *yyRelPointer += (yyvsp[-2].Number) * (yyvsp[-1].Number) * (yyvsp[0].Number);
	}

    break;


  case 58: /* relunits: INTNUM unit  */
                      {
	    *yyRelPointer += (yyvsp[-1].Number) * (yyvsp[0].Number);
	}

    break;


  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 61: /* relunits: unit  */
               {
	    *yyRelPointer += (yyvsp[0].Number);
	}

    break;


  case 62: /* sign: '-'  */
              {
	    (yyval.Number) = -1;
	}

    break;


  case 63: /* sign: '+'  */
              {
	    (yyval.Number) =  1;
	}

    break;


  case 64: /* unit: tSEC_UNIT  */
                    {
	    (yyval.Number) = (yyvsp[0].Number);
	    yyRelPointer = &yyRelSeconds;
	}

    break;


  case 65: /* unit: tDAY_UNIT  */
                    {
	    (yyval.Number) = (yyvsp[0].Number);
	    yyRelPointer = &yyRelDay;
	}

    break;


  case 66: /* unit: tMONTH_UNIT  */
                      {
	    (yyval.Number) = (yyvsp[0].Number);
	    yyRelPointer = &yyRelMonth;
	}
    break;

  case 67: /* INTNUM: tUNUMBER  */
                   {
	    (yyval.Number) = (yyvsp[0].Number);
	}
    break;

  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 {
		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 71: /* o_merid: %empty  */
                     {
	    (yyval.Meridian) = MER24;
	}

    break;


  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 ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc);

  YYPOPSTACK (yylen);
  yylen = 0;


  *++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.  */
  {
    const int yylhs = yyr1[yyn] - YYNTOKENS;
    const int yyi = yypgoto[yylhs] + *yyssp;

    yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp
               ? yytable[yyi]

               : 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 ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar);

  /* If not already recovering from an error, report this error.  */
  if (!yyerrstatus)
    {


      yyerror (&yylloc, info, YY_("syntax error"));



















    }














  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
  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
     code.  */
  if (/*CONSTCOND*/ 0)
     goto yyerrorlab;


  /* 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.  */


  for (;;)
    {
      yyn = yypact[yystate];
      if (!yypact_value_is_default (yyn))
        {
          yyn += YYTERROR;
          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
            {
              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);
      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;


  /* Shift the error token.  */
  YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);

  yystate = yyn;
  goto yynewstate;


/*-------------------------------------.
| yyacceptlab -- YYACCEPT comes here.  |
`-------------------------------------*/
yyacceptlab:
  yyresult = 0;
  goto yyreturn;


/*-----------------------------------.
| yyabortlab -- YYABORT comes here.  |
`-----------------------------------*/
yyabortlab:
  yyresult = 1;
  goto yyreturn;

#if !defined yyoverflow || YYERROR_VERBOSE
/*-------------------------------------------------.
| yyexhaustedlab -- memory exhaustion comes here.  |
`-------------------------------------------------*/
yyexhaustedlab:
  yyerror (&yylloc, info, YY_("memory exhausted"));
  yyresult = 2;
  /* Fall through.  */
#endif




yyreturn:
  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);
      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.
 */







<
|
|
<
|
<
>
















>





|
|













|










<
<
<
|
>


|










|
>






|

|
|
|
|



|
|

>
>
>
|















|






|
<
<
<







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
  goto yyerrlab1;


/*---------------------------------------------------.
| yyerrorlab -- error raised explicitly by YYERROR.  |
`---------------------------------------------------*/
yyerrorlab:

  /* Pacify compilers when the user code never invokes YYERROR and the
     label yyerrorlab therefore never appears in user code.  */

  if (0)

    YYERROR;

  /* 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 += 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",
                  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;



  ++yylsp;
  YYLLOC_DEFAULT (*yylsp, yyerror_range, 2);

  /* Shift the error token.  */
  YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp);

  yystate = yyn;
  goto yynewstate;


/*-------------------------------------.
| yyacceptlab -- YYACCEPT comes here.  |
`-------------------------------------*/
yyacceptlab:
  yyresult = 0;
  goto yyreturnlab;


/*-----------------------------------.
| yyabortlab -- YYABORT comes here.  |
`-----------------------------------*/
yyabortlab:
  yyresult = 1;
  goto yyreturnlab;


/*-----------------------------------------------------------.
| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here.  |
`-----------------------------------------------------------*/
yyexhaustedlab:
  yyerror (&yylloc, info, YY_("memory exhausted"));
  yyresult = 2;
  goto yyreturnlab;


/*----------------------------------------------------------.
| yyreturnlab -- parsing is finished, clean up and return.  |
`----------------------------------------------------------*/
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",
                  YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, yylsp, info);
      YYPOPSTACK (1);
    }
#ifndef yyoverflow
  if (yyss != yyssa)
    YYSTACK_FREE (yyss);
#endif




  return yyresult;
}


/*
 * Month and day table.
 */
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
    { "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 }
};

/*







<
<
<
<
<
<
<
<
<
<
<
<
<
<







2160
2161
2162
2163
2164
2165
2166














2167
2168
2169
2170
2171
2172
2173
    { "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 },














    { "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
    { "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 */


    { "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 */







>
>







2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
    { "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
    { "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
     * 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!) */







|







2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
    { "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 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
};

/*
 * 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) },
    { NULL, 0, 0 }
};











/*
 * Dump error messages in the bit bucket.
 */

static void
TclDateerror(
    YYLTYPE* location,
    DateInfo* infoPtr,
    const char *s)
{
    Tcl_Obj* t;



    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
ToSeconds(
    time_t Hours,
    time_t Minutes,
    time_t 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;
    case MERam:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	}
	return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
    case MERpm:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	}
	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) {
	yylvalPtr->Meridian = MERam;
	return tMERIDIAN;
    }
    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
	yylvalPtr->Meridian = MERpm;
	return tMERIDIAN;
    }

    /*
     * See if we have an abbreviation for a month.
     */







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


>
>
>
>
>
>
>
>
>
>












>
>
>
















|

|
|
|










|




|




|




















|



|







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
};

/*
 * Military timezone table.
 */

static const TABLE MilitaryTable[] = {
    { "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";
}

int
ToSeconds(
    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 * 60 + Minutes) * 60 + Seconds;
    case MERam:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	}
	return ((Hours % 12) * 60 + Minutes) * 60 + Seconds;
    case MERpm:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	}
	return (((Hours % 12) + 12) * 60 + Minutes) * 60 + 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 (*buff == 'a' && (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0)) {
	yylvalPtr->Meridian = MERam;
	return tMERIDIAN;
    }
    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
    YYLTYPE* location,
    DateInfo *info)
{
    char c;
    char *p;
    char buff[20];
    int Count;


    location->first_column = yyInput - info->dateStart;
    for ( ; ; ) {
	while (TclIsSpaceProcM(*yyInput)) {



	    yyInput++;


	}



	if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */

	    /*
	     * Convert the string into a number; count the number of digits.
	     */


	    Count = 0;

	    for (yylvalPtr->Number = 0;





		    isdigit(UCHAR(c = *yyInput++)); ) {	  /* INTL: digit */
		yylvalPtr->Number = 10 * yylvalPtr->Number + c - '0';
		Count++;

	    }

	    yyInput--;




	    yyDigitCount = Count;





	    /*
	     * 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;
	    } else {

		location->last_column = yyInput - info->dateStart - 1;
		return tUNUMBER;
	    }
	}




	if (!(c & 0x80) && isalpha(UCHAR(c))) {		  /* INTL: ISO only. */

	    for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
		     || c == '.'; ) {
		if (p < &buff[sizeof buff - 1]) {
		    *p++ = c;
		}
	    }
	    *p = '\0';
	    yyInput--;
	    location->last_column = yyInput - info->dateStart - 1;
	    return LookupWord(yylvalPtr, buff);






























	}
	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(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Count of paraneters */
    Tcl_Obj *const *objv)	/* 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]);
    dateInfo.dateStart = yyInput;

    yyHaveDate = 0;
    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;

    yyHaveOrdinalMonth = 0;
    yyMonthOrdinal = 0;

    yyHaveDay = 0;
    yyDayOrdinal = 0; yyDayNumber = 0;


    yyHaveRel = 0;
    yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;

    TclNewObj(dateInfo.messages);
    dateInfo.separatrix = "";
    Tcl_IncrRefCount(dateInfo.messages);

    status = yyparse(&dateInfo);
    if (status == 1) {
















	Tcl_SetObjResult(interp, dateInfo.messages);

	Tcl_DecrRefCount(dateInfo.messages);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);

	return 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;
    } 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_DecrRefCount(dateInfo.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;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>



|
>
>
>
|
>
>
|
|
>
>

>

|

|
>
|
>
|
>
>
>
>
>
|
|
<
>
|
>
|
>
>
>
>
|
>
>
>
|
>



<
<
|
>
>
|
<
>
|
|
|
|
>
>
>
>

>


|






|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



















|

|
<

<
|

<
<
<
<


|
|
|
|
|
|
|
<
|
|
<
<
<
<
<
<
|
<
<

<
|

<
|

|
<

>
|
<

<
<
<
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
|


<
|
|





<
|
|

>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|









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
    YYLTYPE* location,
    DateInfo *info)
{
    char c;
    char *p;
    char buff[20];
    int Count;
    const char *tokStart;

    location->first_column = yyInput - info->dateStart;
    for ( ; ; ) {

	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 */

	    /*
	     * Count the number of digits.
	     */
	    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) {

		    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.
	     */


	    location->last_column = yyInput - info->dateStart - 1;
	    if (yyDigitCount >= 6) {
		if (yyDigitCount == 8) {
		    return tISOBAS8;

		}
		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]) {
		    *p++ = c;
		}
	    }
	    *p = '\0';
	    yyInput--;
	    location->last_column = yyInput - info->dateStart - 1;
	    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
TclClockFreeScan(

    Tcl_Interp *interp,		/* Tcl interpreter */

    DateInfo *info)		/* Input and result parameters */
{




    int status;

  #if YYDEBUG
    /* enable debugging if compiled with YYDEBUG */
    yydebug = 1;
  #endif

    /*
     * yyInput = stringToParse;

     *
     * ClockInitDateInfo(info) should be executed to pre-init info;






     */




    yyDSTmode = DSTmaybe;


    info->separatrix = "";

    info->dateStart = yyInput;


    /* ignore spaces at begin */
    yyInput = bypassSpaces(yyInput);





    /* 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,
		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_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_SetErrorCode(interp, "TCL", "BUG", (char *)NULL);
	status = TCL_ERROR;
    }
    if (info->messages) {
	Tcl_DecrRefCount(info->messages);
    }

























































































    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
 * 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



#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
#   define TCL_STORAGE_CLASS DLLEXPORT
#else
#   ifdef USE_TCL_STUBS
#      define TCL_STORAGE_CLASS
#   else







>
>







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
/* 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);
/* 4 */
EXTERN void		Tcl_Free(void *ptr);
/* 5 */
EXTERN void *		Tcl_Realloc(void *ptr, size_t size);
/* 6 */
EXTERN void *		Tcl_DbCkalloc(size_t 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,
				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);
/* 17 */
EXTERN Tcl_Obj *	Tcl_ConcatObj(int 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);

/* 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,
				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);
/* 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);
/* 32 */
EXTERN int		Tcl_GetBooleanFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, int *boolPtr);
/* 33 */
EXTERN unsigned char *	Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr,
				int *lengthPtr);
/* 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);
/* 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,
				Tcl_Obj ***objvPtr);
/* 46 */
EXTERN int		Tcl_ListObjIndex(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int index,
				Tcl_Obj **objPtrPtr);
/* 47 */
EXTERN int		Tcl_ListObjLength(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int *lengthPtr);
/* 48 */
EXTERN int		Tcl_ListObjReplace(Tcl_Interp *interp,
				Tcl_Obj *listPtr, int first, int count,

				int objc, Tcl_Obj *const objv[]);
/* Slot 49 is reserved */
/* 50 */
EXTERN Tcl_Obj *	Tcl_NewByteArrayObj(const unsigned char *bytes,
				size_t length);
/* 51 */
EXTERN Tcl_Obj *	Tcl_NewDoubleObj(double doubleValue);
/* Slot 52 is reserved */
/* 53 */
EXTERN Tcl_Obj *	Tcl_NewListObj(int 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);
/* Slot 57 is reserved */
/* 58 */
EXTERN unsigned char *	Tcl_SetByteArrayLength(Tcl_Obj *objPtr,
				size_t length);
/* 59 */
EXTERN void		Tcl_SetByteArrayObj(Tcl_Obj *objPtr,
				const unsigned char *bytes, size_t length);

/* 60 */
EXTERN void		Tcl_SetDoubleObj(Tcl_Obj *objPtr, double doubleValue);
/* Slot 61 is reserved */
/* 62 */
EXTERN void		Tcl_SetListObj(Tcl_Obj *objPtr, int objc,
				Tcl_Obj *const objv[]);
/* Slot 63 is reserved */
/* 64 */
EXTERN void		Tcl_SetObjLength(Tcl_Obj *objPtr, size_t length);
/* 65 */
EXTERN void		Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes,
				size_t 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);







|



|

|




|

<



<
<
<
<
<
<
<


<
<
<
<
<













|

|















|
>




|





|
|






|


|


|



















|









|
|



|


|
|


|
>
|



|




|




|



|


|
>




|



|


|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

77
78
79







80
81





82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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(TCL_HASH_TYPE size);
/* 4 */
EXTERN void		Tcl_Free(void *ptr);
/* 5 */
EXTERN void *		Tcl_Realloc(void *ptr, TCL_HASH_TYPE size);
/* 6 */
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, TCL_HASH_TYPE size,
				const char *file, int line);

/* 9 */
EXTERN void		Tcl_CreateFileHandler(int fd, int mask,
				Tcl_FileProc *proc, void *clientData);







/* 10 */
EXTERN void		Tcl_DeleteFileHandler(int fd);





/* 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,
				Tcl_Size length);
/* 17 */
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,
				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(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,
				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 *intPtr);
/* 32 */
EXTERN int		Tcl_GetBooleanFromObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, int *intPtr);
/* 33 */
EXTERN unsigned char *	Tcl_GetByteArrayFromObj(Tcl_Obj *objPtr,
				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 *		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		TclListObjGetElements(Tcl_Interp *interp,
				Tcl_Obj *listPtr, void *objcPtr,
				Tcl_Obj ***objvPtr);
/* 46 */
EXTERN int		Tcl_ListObjIndex(Tcl_Interp *interp,
				Tcl_Obj *listPtr, Tcl_Size index,
				Tcl_Obj **objPtrPtr);
/* 47 */
EXTERN int		TclListObjLength(Tcl_Interp *interp,
				Tcl_Obj *listPtr, void *lengthPtr);
/* 48 */
EXTERN int		Tcl_ListObjReplace(Tcl_Interp *interp,
				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,
				Tcl_Size numBytes);
/* 51 */
EXTERN Tcl_Obj *	Tcl_NewDoubleObj(double doubleValue);
/* Slot 52 is reserved */
/* 53 */
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, Tcl_Size length);
/* Slot 57 is reserved */
/* 58 */
EXTERN unsigned char *	Tcl_SetByteArrayLength(Tcl_Obj *objPtr,
				Tcl_Size numBytes);
/* 59 */
EXTERN void		Tcl_SetByteArrayObj(Tcl_Obj *objPtr,
				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, Tcl_Size objc,
				Tcl_Obj *const objv[]);
/* Slot 63 is reserved */
/* 64 */
EXTERN void		Tcl_SetObjLength(Tcl_Obj *objPtr, Tcl_Size length);
/* 65 */
EXTERN void		Tcl_SetStringObj(Tcl_Obj *objPtr, const char *bytes,
				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
				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 */

/* 82 */
EXTERN int		Tcl_CommandComplete(const char *cmd);
/* 83 */
EXTERN char *		Tcl_Concat(int argc, const char *const *argv);
/* 84 */
EXTERN size_t		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);
/* 86 */
EXTERN int		Tcl_CreateAlias(Tcl_Interp *childInterp,
				const char *childCmd, Tcl_Interp *target,
				const char *targetCmd, int argc,
				const char *const *argv);
/* 87 */
EXTERN int		Tcl_CreateAliasObj(Tcl_Interp *childInterp,
				const char *childCmd, Tcl_Interp *target,
				const char *targetCmd, int 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,







|
>



|

|


|
|



|




|







243
244
245
246
247
248
249
250
251
252
253
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);
/* 81 */
EXTERN int		Tcl_Close(Tcl_Interp *interp, Tcl_Channel chan);
/* 82 */
EXTERN int		Tcl_CommandComplete(const char *cmd);
/* 83 */
EXTERN char *		Tcl_Concat(Tcl_Size argc, const char *const *argv);
/* 84 */
EXTERN Tcl_Size		Tcl_ConvertElement(const char *src, char *dst,
				int flags);
/* 85 */
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, Tcl_Size argc,
				const char *const *argv);
/* 87 */
EXTERN int		Tcl_CreateAliasObj(Tcl_Interp *childInterp,
				const char *childCmd, Tcl_Interp *target,
				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
/* 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,
				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);







|







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, 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
/* 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);
/* 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);
/* 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);
/* 125 */
EXTERN void		Tcl_DStringStartSublist(Tcl_DString *dsPtr);
/* 126 */
EXTERN int		Tcl_Eof(Tcl_Channel chan);
/* 127 */
EXTERN const char *	Tcl_ErrnoId(void);
/* 128 */







|













|

















|







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(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, 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,
				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 */
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
/* 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 */

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,
				const char *childCmd,
				Tcl_Interp **targetInterpPtr,
				const char **targetCmdPtr, int *objcPtr,
				Tcl_Obj ***objv);
/* 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);
/* 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);







>
|


















|







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
/* 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 */
TCL_DEPRECATED("Use Tcl_GetAliasObj")
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,
				const char *childCmd,
				Tcl_Interp **targetInterpPtr,
				const char **targetCmdPtr, int *objcPtr,
				Tcl_Obj ***objv);
/* 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 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
				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);
/* 170 */
EXTERN size_t		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 */







<




<
<
<
<
<
<
<



|

|







479
480
481
482
483
484
485

486
487
488
489







490
491
492
493
494
495
496
497
498
499
500
501
502
				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);

/* 167 */
EXTERN int		Tcl_GetOpenFile(Tcl_Interp *interp,
				const char *chanID, int forWriting,
				int checkUsage, void **filePtr);







/* 168 */
EXTERN Tcl_PathType	Tcl_GetPathType(const char *path);
/* 169 */
EXTERN Tcl_Size		Tcl_Gets(Tcl_Channel chan, Tcl_DString *dsPtr);
/* 170 */
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
/* 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,
				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 */
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);
/* 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);
/* 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);
/* 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,
				Tcl_QueuePosition position);
/* 206 */
EXTERN size_t		Tcl_Read(Tcl_Channel chan, char *bufPtr,
				size_t 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,







|







|
<



|












|
|







|















|
<

|
|







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
/* 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(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);
/* Slot 190 is reserved */

/* 191 */
EXTERN Tcl_Channel	Tcl_MakeTcpClientChannel(void *tcpSocket);
/* 192 */
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,
				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 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, int position);

/* 206 */
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
/* 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,
				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);
/* 219 */
EXTERN size_t		Tcl_ScanCountedElement(const char *src,
				size_t 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);

/* 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);

/* Slot 232 is reserved */
/* 233 */
EXTERN int		Tcl_SetServiceMode(int mode);
/* 234 */
EXTERN void		Tcl_SetObjErrorCode(Tcl_Interp *interp,
				Tcl_Obj *errorObjPtr);
/* 235 */







|






|

|
|










|
>
















|
>







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
/* 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, 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 Tcl_Size		Tcl_ScanElement(const char *src, int *flagPtr);
/* 219 */
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,
				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 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
/* 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,
				const char *listStr, int *argcPtr,
				const char ***argvPtr);
/* 243 */
EXTERN void		Tcl_SplitPath(const char *path, int *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);
/* 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 */







|
<
|

|













|
|







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
/* 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		TclSplitList(Tcl_Interp *interp, const char *listStr,

				void *argcPtr, const char ***argvPtr);
/* 243 */
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 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
/* 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);
/* 264 */
EXTERN void		Tcl_WrongNumArgs(Tcl_Interp *interp, int 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 */







|
|

|







713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
/* 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 Tcl_Size		Tcl_Write(Tcl_Channel chan, const char *s,
				Tcl_Size slen);
/* 264 */
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 */
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
				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);
/* 292 */
EXTERN int		Tcl_EvalObjv(Tcl_Interp *interp, int 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_EncodingState *statePtr, char *dst,
				size_t dstLen, int *srcReadPtr,
				int *dstWrotePtr, int *dstCharsPtr);
/* 296 */
EXTERN char *		Tcl_ExternalToUtfDString(Tcl_Encoding encoding,
				const char *src, size_t 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);
/* 305 */
EXTERN void *		Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr,
				size_t 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);
/* 313 */
EXTERN size_t		Tcl_ReadChars(Tcl_Channel channel, Tcl_Obj *objPtr,
				size_t 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);
/* 320 */
EXTERN int		Tcl_UniCharAtIndex(const char *src, size_t 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);
/* 325 */
EXTERN const char *	Tcl_UtfAtIndex(const char *src, size_t index);
/* 326 */
EXTERN int		Tcl_UtfCharComplete(const char *src, size_t length);
/* 327 */
EXTERN size_t		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);
/* 331 */
EXTERN const char *	Tcl_UtfPrev(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_EncodingState *statePtr, char *dst,
				size_t dstLen, int *srcReadPtr,
				int *dstWrotePtr, int *dstCharsPtr);
/* 333 */
EXTERN char *		Tcl_UtfToExternalDString(Tcl_Encoding encoding,
				const char *src, size_t srcLen,
				Tcl_DString *dsPtr);
/* 334 */
EXTERN int		Tcl_UtfToLower(char *src);
/* 335 */
EXTERN int		Tcl_UtfToTitle(char *src);
/* 336 */
EXTERN int		Tcl_UtfToChar16(const char *src,
				unsigned short *chPtr);
/* 337 */
EXTERN int		Tcl_UtfToUpper(char *src);
/* 338 */
EXTERN size_t		Tcl_WriteChars(Tcl_Channel chan, const char *src,
				size_t srcLen);
/* 339 */
EXTERN size_t		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 */







|

|









|

|



|


















|
|


|















|

|
|













|

|







|

|

|

|






|

|



|

|



|


|

|

|


|

|
|

|







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
				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,
				Tcl_Size numBytes, int flags);
/* 292 */
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,
				Tcl_Size srcLen, int flags,
				Tcl_EncodingState *statePtr, char *dst,
				Tcl_Size dstLen, int *srcReadPtr,
				int *dstWrotePtr, int *dstCharsPtr);
/* 296 */
EXTERN char *		Tcl_ExternalToUtfDString(Tcl_Encoding encoding,
				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,
				Tcl_Size offset, const char *msg, int flags,
				void *indexPtr);
/* 305 */
EXTERN void *		Tcl_GetThreadData(Tcl_ThreadDataKey *keyPtr,
				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 Tcl_Size		TclNumUtfChars(const char *src, Tcl_Size length);
/* 313 */
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, int position);
/* 320 */
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 Tcl_Size		Tcl_UniCharToUtf(int ch, char *buf);
/* 325 */
EXTERN const char *	TclUtfAtIndex(const char *src, Tcl_Size index);
/* 326 */
EXTERN int		TclUtfCharComplete(const char *src, Tcl_Size length);
/* 327 */
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 *	TclUtfNext(const char *src);
/* 331 */
EXTERN const char *	TclUtfPrev(const char *src, const char *start);
/* 332 */
EXTERN 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);
/* 333 */
EXTERN char *		Tcl_UtfToExternalDString(Tcl_Encoding encoding,
				const char *src, Tcl_Size srcLen,
				Tcl_DString *dsPtr);
/* 334 */
EXTERN Tcl_Size		Tcl_UtfToLower(char *src);
/* 335 */
EXTERN Tcl_Size		Tcl_UtfToTitle(char *src);
/* 336 */
EXTERN Tcl_Size		Tcl_UtfToChar16(const char *src,
				unsigned short *chPtr);
/* 337 */
EXTERN Tcl_Size		Tcl_UtfToUpper(char *src);
/* 338 */
EXTERN Tcl_Size		Tcl_WriteChars(Tcl_Channel chan, const char *src,
				Tcl_Size srcLen);
/* 339 */
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
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 */

/* Slot 353 is reserved */
/* 354 */
EXTERN char *		Tcl_Char16ToUtfDString(const unsigned short *uniStr,
				size_t uniLength, Tcl_DString *dsPtr);
/* 355 */
EXTERN unsigned short *	 Tcl_UtfToChar16DString(const char *src,
				size_t 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);
/* 360 */
EXTERN int		Tcl_ParseBraces(Tcl_Interp *interp,
				const char *start, size_t numBytes,
				Tcl_Parse *parsePtr, int append,
				const char **termPtr);
/* 361 */
EXTERN int		Tcl_ParseCommand(Tcl_Interp *interp,
				const char *start, size_t numBytes,
				int nested, Tcl_Parse *parsePtr);
/* 362 */
EXTERN int		Tcl_ParseExpr(Tcl_Interp *interp, const char *start,
				size_t numBytes, Tcl_Parse *parsePtr);
/* 363 */
EXTERN int		Tcl_ParseQuotedString(Tcl_Interp *interp,
				const char *start, size_t numBytes,
				Tcl_Parse *parsePtr, int append,
				const char **termPtr);
/* 364 */
EXTERN int		Tcl_ParseVarName(Tcl_Interp *interp,
				const char *start, size_t 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);
/* 370 */
EXTERN int		Tcl_UtfNcasecmp(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,

				size_t offset, size_t nmatches, 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);
/* 379 */
EXTERN void		Tcl_SetUnicodeObj(Tcl_Obj *objPtr,
				const Tcl_UniChar *unicode, size_t numChars);

/* 380 */
EXTERN size_t		Tcl_GetCharLength(Tcl_Obj *objPtr);
/* 381 */
EXTERN int		Tcl_GetUniChar(Tcl_Obj *objPtr, size_t index);
/* Slot 382 is reserved */
/* 383 */
EXTERN Tcl_Obj *	Tcl_GetRange(Tcl_Obj *objPtr, size_t first,
				size_t last);
/* Slot 384 is reserved */


/* 385 */
EXTERN int		Tcl_RegExpMatchObj(Tcl_Interp *interp,
				Tcl_Obj *textObj, Tcl_Obj *patternObj);
/* 386 */
EXTERN void		Tcl_SetNotifier(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[]);
/* 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);
/* 394 */
EXTERN size_t		Tcl_ReadRaw(Tcl_Channel chan, char *dst,
				size_t bytesToRead);
/* 395 */
EXTERN size_t		Tcl_WriteRaw(Tcl_Channel chan, const char *src,
				size_t 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 */







|
>



|


|









|


|




|



|


|




|










|

|















>
|





|


|
>

|

|


|
|
|
>
>




|
>









|







|

|
|

|
|







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
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);
/* 352 */
EXTERN Tcl_Size		Tcl_Char16Len(const unsigned short *uniStr);
/* Slot 353 is reserved */
/* 354 */
EXTERN char *		Tcl_Char16ToUtfDString(const unsigned short *uniStr,
				Tcl_Size uniLength, Tcl_DString *dsPtr);
/* 355 */
EXTERN unsigned short *	 Tcl_UtfToChar16DString(const char *src,
				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,
				Tcl_Size length);
/* 360 */
EXTERN int		Tcl_ParseBraces(Tcl_Interp *interp,
				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, Tcl_Size numBytes,
				int nested, Tcl_Parse *parsePtr);
/* 362 */
EXTERN int		Tcl_ParseExpr(Tcl_Interp *interp, const char *start,
				Tcl_Size numBytes, Tcl_Parse *parsePtr);
/* 363 */
EXTERN int		Tcl_ParseQuotedString(Tcl_Interp *interp,
				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, 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		TclUtfNcmp(const char *s1, const char *s2, size_t n);
/* 370 */
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,
				int flags);
/* 377 */
EXTERN void		Tcl_RegExpGetInfo(Tcl_RegExp regexp,
				Tcl_RegExpInfo *infoPtr);
/* 378 */
EXTERN Tcl_Obj *	Tcl_NewUnicodeObj(const Tcl_UniChar *unicode,
				Tcl_Size numChars);
/* 379 */
EXTERN void		Tcl_SetUnicodeObj(Tcl_Obj *objPtr,
				const Tcl_UniChar *unicode,
				Tcl_Size numChars);
/* 380 */
EXTERN Tcl_Size		TclGetCharLength(Tcl_Obj *objPtr);
/* 381 */
EXTERN int		TclGetUniChar(Tcl_Obj *objPtr, Tcl_Size index);
/* Slot 382 is reserved */
/* 383 */
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(
				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,
				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,
				TCL_HASH_TYPE stackSize, int flags);
/* 394 */
EXTERN Tcl_Size		Tcl_ReadRaw(Tcl_Channel chan, char *dst,
				Tcl_Size bytesToRead);
/* 395 */
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
				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);
/* 429 */
EXTERN void *		Tcl_AttemptDbCkalloc(size_t size, const char *file,
				int line);
/* 430 */
EXTERN void *		Tcl_AttemptRealloc(void *ptr, size_t size);
/* 431 */
EXTERN void *		Tcl_AttemptDbCkrealloc(void *ptr, size_t size,
				const char *file, int line);
/* 432 */
EXTERN int		Tcl_AttemptSetObjLength(Tcl_Obj *objPtr,
				size_t length);
/* 433 */
EXTERN Tcl_ThreadId	Tcl_GetChannelThread(Tcl_Channel channel);
/* 434 */
EXTERN Tcl_UniChar *	Tcl_GetUnicodeFromObj(Tcl_Obj *objPtr,
				int *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,







|

|
|

|

|



|



|
|







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
				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(TCL_HASH_TYPE size);
/* 429 */
EXTERN void *		Tcl_AttemptDbCkalloc(TCL_HASH_TYPE size,
				const char *file, int line);
/* 430 */
EXTERN void *		Tcl_AttemptRealloc(void *ptr, TCL_HASH_TYPE size);
/* 431 */
EXTERN void *		Tcl_AttemptDbCkrealloc(void *ptr, TCL_HASH_TYPE size,
				const char *file, int line);
/* 432 */
EXTERN int		Tcl_AttemptSetObjLength(Tcl_Obj *objPtr,
				Tcl_Size length);
/* 433 */
EXTERN Tcl_ThreadId	Tcl_GetChannelThread(Tcl_Channel channel);
/* 434 */
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
/* 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_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 */







|
|







1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
/* 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_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
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);
/* 461 */
EXTERN Tcl_Obj *	Tcl_FSSplitPath(Tcl_Obj *pathPtr, int *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,
				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);







|

|







|







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
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, Tcl_Size elements);
/* 461 */
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, 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
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);
/* 482 */
EXTERN void		Tcl_GetTime(Tcl_Time *timeBuf);
/* 483 */
EXTERN Tcl_Trace	Tcl_CreateObjTrace(Tcl_Interp *interp, int 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,







|



|
>
|







1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
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, Tcl_Size count);
/* 482 */
EXTERN void		Tcl_GetTime(Tcl_Time *timeBuf);
/* 483 */
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
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,
				int mode);
/* 492 */
EXTERN Tcl_WideInt	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);
/* 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 *const *keyv, Tcl_Obj *valuePtr);
/* 502 */
EXTERN int		Tcl_DictObjRemoveKeyList(Tcl_Interp *interp,
				Tcl_Obj *dictPtr, int 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,







|


|













|
|













|



|







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
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 long long	Tcl_Seek(Tcl_Channel chan, long long offset,
				int mode);
/* 492 */
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		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, Tcl_Size keyc,
				Tcl_Obj *const *keyv, Tcl_Obj *valuePtr);
/* 502 */
EXTERN int		Tcl_DictObjRemoveKeyList(Tcl_Interp *interp,
				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
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);
/* 526 */
EXTERN void		Tcl_LimitSetTime(Tcl_Interp *interp,
				Tcl_Time *timeLimitPtr);
/* 527 */
EXTERN void		Tcl_LimitSetGranularity(Tcl_Interp *interp, int type,
				int granularity);
/* 528 */







|







1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
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,
				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
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);
/* 561 */
EXTERN Tcl_DriverTruncateProc * Tcl_ChannelTruncateProc(
				const Tcl_ChannelType *chanTypePtr);
/* 562 */
EXTERN void		Tcl_SetChannelErrorInterp(Tcl_Interp *interp,
				Tcl_Obj *msg);
/* 563 */







|







1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
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,
				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
/* 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,
				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);
/* 576 */
EXTERN Tcl_Obj *	Tcl_Format(Tcl_Interp *interp, const char *format,
				int 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[]);
/* 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,







|






|
|


|



|







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
/* 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, 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, Tcl_Size length,
				Tcl_Size limit, const char *ellipsis);
/* 576 */
EXTERN Tcl_Obj *	Tcl_Format(Tcl_Interp *interp, const char *format,
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 577 */
EXTERN int		Tcl_AppendFormatToObj(Tcl_Interp *interp,
				Tcl_Obj *objPtr, const char *format,
				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
				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,
				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);

/* 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[]);
/* 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);
/* 597 */
EXTERN Tcl_WideInt	Tcl_GetModificationTimeFromStat(
				const Tcl_StatBuf *statPtr);
/* 598 */
EXTERN Tcl_WideInt	Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr);
/* 599 */
EXTERN Tcl_WideUInt	Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr);
/* 600 */
EXTERN Tcl_WideUInt	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,
				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 *gzipHeaderDictObj);
/* 612 */
EXTERN unsigned int	Tcl_ZlibCRC32(unsigned int crc,
				const unsigned char *buf, size_t len);
/* 613 */
EXTERN unsigned int	Tcl_ZlibAdler32(unsigned int adler,
				const unsigned char *buf, size_t 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);
/* 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);







|



|
>







|















|

|


|

|

|









|
|


















|



|


|















|







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
				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, Tcl_Size objc,
				Tcl_Obj *const objv[], int flags);
/* 586 */
EXTERN int		Tcl_NRCmdSwap(Tcl_Interp *interp, Tcl_Command cmd,
				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,
				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 long long	Tcl_GetAccessTimeFromStat(const Tcl_StatBuf *statPtr);
/* 597 */
EXTERN long long	Tcl_GetModificationTimeFromStat(
				const Tcl_StatBuf *statPtr);
/* 598 */
EXTERN long long	Tcl_GetChangeTimeFromStat(const Tcl_StatBuf *statPtr);
/* 599 */
EXTERN unsigned long long Tcl_GetSizeFromStat(const Tcl_StatBuf *statPtr);
/* 600 */
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		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, Tcl_Size buffersize,
				Tcl_Obj *gzipHeaderDictObj);
/* 612 */
EXTERN unsigned int	Tcl_ZlibCRC32(unsigned int crc,
				const unsigned char *buf, Tcl_Size len);
/* 613 */
EXTERN unsigned int	Tcl_ZlibAdler32(unsigned int adler,
				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, 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
/* 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,
				Tcl_TcpAcceptProc *acceptProc,
				void *callbackData);
/* 632 */
EXTERN int		TclZipfs_Mount(Tcl_Interp *interp,
				const char *mountPoint, const char *zipname,
				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 char *mountPoint, unsigned char *data,
				size_t datalen, int copy);
/* 636 */
EXTERN void		Tcl_FreeIntRep(Tcl_Obj *objPtr);
/* 637 */
EXTERN char *		Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes,
				size_t numBytes);
/* 638 */
EXTERN Tcl_ObjIntRep *	Tcl_FetchIntRep(Tcl_Obj *objPtr,
				const Tcl_ObjType *typePtr);
/* 639 */
EXTERN void		Tcl_StoreIntRep(Tcl_Obj *objPtr,
				const Tcl_ObjType *typePtr,
				const Tcl_ObjIntRep *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);
/* 645 */
EXTERN int		Tcl_GetIntForIndex(Tcl_Interp *interp,
				Tcl_Obj *objPtr, size_t endValue,
				size_t *indexPtr);
/* 646 */
EXTERN int		Tcl_UtfToUniChar(const char *src, int *chPtr);
/* 647 */
EXTERN char *		Tcl_UniCharToUtfDString(const int *uniStr,
				size_t uniLength, Tcl_DString *dsPtr);
/* 648 */
EXTERN int *		Tcl_UtfToUniCharDString(const char *src,
				size_t length, Tcl_DString *dsPtr);






























































































































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_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_DbCkfree) (void *ptr, const char *file, int line); /* 7 */
    void * (*tcl_DbCkrealloc) (void *ptr, size_t 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 */
    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_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 */
    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_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_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 */
    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 */
    void (*reserved49)(void);
    Tcl_Obj * (*tcl_NewByteArrayObj) (const unsigned char *bytes, size_t length); /* 50 */
    Tcl_Obj * (*tcl_NewDoubleObj) (double doubleValue); /* 51 */
    void (*reserved52)(void);
    Tcl_Obj * (*tcl_NewListObj) (int 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 */
    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 */
    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 (*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 (*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_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 */
    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 */
    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_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_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_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);







|




|








>
|
<

|


|

|


|

|











|


|
|

|


|


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>














|

|
|

|
<

<
<
<
<
<
<
<
<

<
<
<
<
<
<
<





|
|





|

|


|


|
|
|







|



|
|
|
|

|


|


|

|
|


|

|
|















|

|
|
|
|
|











|











|





|






|







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
/* 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, int backlog,
				Tcl_TcpAcceptProc *acceptProc,
				void *callbackData);
/* 632 */
EXTERN int		TclZipfs_Mount(Tcl_Interp *interp,
				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, int copy);

/* 636 */
EXTERN void		Tcl_FreeInternalRep(Tcl_Obj *objPtr);
/* 637 */
EXTERN char *		Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes,
				TCL_HASH_TYPE numBytes);
/* 638 */
EXTERN Tcl_ObjInternalRep * Tcl_FetchInternalRep(Tcl_Obj *objPtr,
				const Tcl_ObjType *typePtr);
/* 639 */
EXTERN void		Tcl_StoreInternalRep(Tcl_Obj *objPtr,
				const Tcl_ObjType *typePtr,
				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,
				Tcl_Size size);
/* 645 */
EXTERN int		Tcl_GetIntForIndex(Tcl_Interp *interp,
				Tcl_Obj *objPtr, Tcl_Size endValue,
				Tcl_Size *indexPtr);
/* 646 */
EXTERN Tcl_Size		Tcl_UtfToUniChar(const char *src, int *chPtr);
/* 647 */
EXTERN char *		Tcl_UniCharToUtfDString(const int *uniStr,
				Tcl_Size uniLength, Tcl_DString *dsPtr);
/* 648 */
EXTERN int *		Tcl_UtfToUniCharDString(const char *src,
				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);
/* Slot 657 is reserved */
/* 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 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) (TCL_HASH_TYPE size); /* 3 */
    void (*tcl_Free) (void *ptr); /* 4 */
    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, TCL_HASH_TYPE size, const char *file, int line); /* 8 */

    void (*tcl_CreateFileHandler) (int fd, int mask, Tcl_FileProc *proc, void *clientData); /* 9 */








    void (*tcl_DeleteFileHandler) (int fd); /* 10 */







    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, 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, 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) (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, 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 *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 * (*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 (*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, Tcl_Size numBytes); /* 50 */
    Tcl_Obj * (*tcl_NewDoubleObj) (double doubleValue); /* 51 */
    void (*reserved52)(void);
    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, Tcl_Size length); /* 56 */
    void (*reserved57)(void);
    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, Tcl_Size objc, Tcl_Obj *const objv[]); /* 62 */
    void (*reserved63)(void);
    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 */
    int (*tcl_Close) (Tcl_Interp *interp, Tcl_Channel chan); /* 81 */
    int (*tcl_CommandComplete) (const char *cmd); /* 82 */
    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, 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) (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, 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, 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
    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 * (*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 */
    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 */
    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 */
    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 */
    Tcl_Channel (*tcl_MakeTcpClientChannel) (void *tcpSocket); /* 191 */
    char * (*tcl_Merge) (int 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_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_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_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_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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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);







|



|














<

<
<
<
<
<
<
<

|
|















|



|

|




|

|





|
|








|


|
|




|






|










|
|






|












|
|







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
    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);
    TCL_DEPRECATED_API("Use Tcl_GetAliasObj") 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 * (*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 */
    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 */

    int (*tcl_GetOpenFile) (Tcl_Interp *interp, const char *chanID, int forWriting, int checkUsage, void **filePtr); /* 167 */







    Tcl_PathType (*tcl_GetPathType) (const char *path); /* 168 */
    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) (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 */
    void (*reserved190)(void);
    Tcl_Channel (*tcl_MakeTcpClientChannel) (void *tcpSocket); /* 191 */
    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, 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 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, 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, Tcl_Size index, const char **startPtr, const char **endPtr); /* 215 */
    void (*tcl_Release) (void *clientData); /* 216 */
    void (*tcl_ResetResult) (Tcl_Interp *interp); /* 217 */
    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, 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);
    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 (*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 */
    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 */
    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);
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
    void (*tcl_SetMainLoop) (Tcl_MainLoopProc *proc); /* 284 */
    void (*reserved285)(void);
    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_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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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);
    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 */
    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 */
    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 (*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 */
    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 */
    void (*reserved382)(void);
    Tcl_Obj * (*tcl_GetRange) (Tcl_Obj *objPtr, size_t first, size_t last); /* 383 */
    void (*reserved384)(void);
    int (*tcl_RegExpMatchObj) (Tcl_Interp *interp, Tcl_Obj *textObj, Tcl_Obj *patternObj); /* 385 */
    void (*tcl_SetNotifier) (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 */
    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 */
    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 */







|
|


|
|







|
|






|
|





|
|



|
|
|
|


|
|
|
|
|
|
|
|
|
|












|

|
|



|
|
|
|
|
|




|
|





|

|
|
|
|

|
|

|



|


|
|
|







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
    void (*tcl_SetMainLoop) (Tcl_MainLoopProc *proc); /* 284 */
    void (*reserved285)(void);
    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, 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, 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, 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 */
    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, 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 */
    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 * (*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 */
    Tcl_Size (*tcl_Char16Len) (const unsigned short *uniStr); /* 352 */
    void (*reserved353)(void);
    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, 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 (*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, 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, 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 * (*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) (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, 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, 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
    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 */
    Tcl_ThreadId (*tcl_GetChannelThread) (Tcl_Channel channel); /* 433 */
    Tcl_UniChar * (*tcl_GetUnicodeFromObj) (Tcl_Obj *objPtr, int *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_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 */
    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 */
    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 */
    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 */
    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 */
    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 (*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 */
    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 */







|
|
|
|
|

|









|















|
|


|
















|

|







|
|




|



|
|







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
    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) (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 * (*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_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, 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, 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, Tcl_Size count); /* 481 */
    void (*tcl_GetTime) (Tcl_Time *timeBuf); /* 482 */
    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 */
    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 (*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, 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
    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_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 */







|







2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
    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, 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
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 (*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_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_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 */
    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 (*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 */








































} TclStubs;

extern const TclStubs *tclStubsPtr;

#ifdef __cplusplus
}
#endif







|












|

|
|
|







|
|

|







|
|
|
|
|



|






|
|
|





|











|
|


|
|
|
|
|




|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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, 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, 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, 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, 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, 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 */
    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 (*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, 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, 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, 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 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, 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 */
    void (*reserved657)(void);
    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 */
    void (*tclUnusedStubEntry) (void); /* 688 */
} 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
	(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 \







<


<
<
<
<
<
<


<
<
<
<
<







2597
2598
2599
2600
2601
2602
2603

2604
2605






2606
2607





2608
2609
2610
2611
2612
2613
2614
	(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 */

#define Tcl_CreateFileHandler \
	(tclStubsPtr->tcl_CreateFileHandler) /* 9 */






#define Tcl_DeleteFileHandler \
	(tclStubsPtr->tcl_DeleteFileHandler) /* 10 */





#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
	(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 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 Tcl_ListObjIndex \
	(tclStubsPtr->tcl_ListObjIndex) /* 46 */
#define Tcl_ListObjLength \
	(tclStubsPtr->tcl_ListObjLength) /* 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 */







|
|






|
|


|
|







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
	(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 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 TclListObjGetElements \
	(tclStubsPtr->tclListObjGetElements) /* 45 */
#define Tcl_ListObjIndex \
	(tclStubsPtr->tcl_ListObjIndex) /* 46 */
#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
/* 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 */

/* Slot 81 is reserved */
#define Tcl_CommandComplete \
	(tclStubsPtr->tcl_CommandComplete) /* 82 */
#define Tcl_Concat \
	(tclStubsPtr->tcl_Concat) /* 83 */
#define Tcl_ConvertElement \
	(tclStubsPtr->tcl_ConvertElement) /* 84 */
#define Tcl_ConvertCountedElement \







>
|







2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
/* 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 \
	(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 \
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
	(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 \







<


<
<
<
<
<







2895
2896
2897
2898
2899
2900
2901

2902
2903





2904
2905
2906
2907
2908
2909
2910
	(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 */

#define Tcl_GetOpenFile \
	(tclStubsPtr->tcl_GetOpenFile) /* 167 */





#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
#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 */
#define Tcl_MakeTcpClientChannel \
	(tclStubsPtr->tcl_MakeTcpClientChannel) /* 191 */
#define Tcl_Merge \
	(tclStubsPtr->tcl_Merge) /* 192 */
#define Tcl_NextHashEntry \
	(tclStubsPtr->tcl_NextHashEntry) /* 193 */
#define Tcl_NotifyChannel \







<
|







2936
2937
2938
2939
2940
2941
2942

2943
2944
2945
2946
2947
2948
2949
2950
#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 */

/* 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
	(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 */
/* 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 \







|
|
|
|







3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
	(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 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 \
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
	(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 Tcl_ReadChars \
	(tclStubsPtr->tcl_ReadChars) /* 313 */
/* Slot 314 is reserved */
/* Slot 315 is reserved */
#define Tcl_SetSystemEncoding \
	(tclStubsPtr->tcl_SetSystemEncoding) /* 316 */
#define Tcl_SetVar2Ex \







|
|







3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
	(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 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
	(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 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 Tcl_UtfToExternal \
	(tclStubsPtr->tcl_UtfToExternal) /* 332 */
#define Tcl_UtfToExternalDString \
	(tclStubsPtr->tcl_UtfToExternalDString) /* 333 */
#define Tcl_UtfToLower \
	(tclStubsPtr->tcl_UtfToLower) /* 334 */
#define Tcl_UtfToTitle \







|
|
|
|






|
|
|
|







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
	(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 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 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
	(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 */

/* Slot 352 is reserved */
/* 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 */







>
|







3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
	(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 \
	(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
	(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 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 */
/* Slot 382 is reserved */
#define Tcl_GetRange \
	(tclStubsPtr->tcl_GetRange) /* 383 */

/* Slot 384 is reserved */
#define Tcl_RegExpMatchObj \
	(tclStubsPtr->tcl_RegExpMatchObj) /* 385 */
#define Tcl_SetNotifier \
	(tclStubsPtr->tcl_SetNotifier) /* 386 */
#define Tcl_GetAllocMutex \
	(tclStubsPtr->tcl_GetAllocMutex) /* 387 */
#define Tcl_GetChannelNames \







|
|
|
|


















|
|
|
|

|
|
>
|







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
	(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 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 TclGetCharLength \
	(tclStubsPtr->tclGetCharLength) /* 380 */
#define TclGetUniChar \
	(tclStubsPtr->tclGetUniChar) /* 381 */
/* Slot 382 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
	(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 */
/* 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 \







|
|







3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
	(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 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
	(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 Tcl_FSEqualPaths \
	(tclStubsPtr->tcl_FSEqualPaths) /* 462 */
#define Tcl_FSGetNormalizedPath \
	(tclStubsPtr->tcl_FSGetNormalizedPath) /* 463 */
#define Tcl_FSJoinToPath \
	(tclStubsPtr->tcl_FSJoinToPath) /* 464 */
#define Tcl_FSGetInternalRep \







|
|







3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
	(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 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
	(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 Tcl_DictObjFirst \
	(tclStubsPtr->tcl_DictObjFirst) /* 498 */
#define Tcl_DictObjNext \
	(tclStubsPtr->tcl_DictObjNext) /* 499 */
#define Tcl_DictObjDone \
	(tclStubsPtr->tcl_DictObjDone) /* 500 */
#define Tcl_DictObjPutKeyList \







|
|







3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
	(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 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
	(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 Tcl_GetErrorLine \
	(tclStubsPtr->tcl_GetErrorLine) /* 605 */
#define Tcl_SetErrorLine \
	(tclStubsPtr->tcl_SetErrorLine) /* 606 */
#define Tcl_TransferResult \
	(tclStubsPtr->tcl_TransferResult) /* 607 */
#define Tcl_InterpActive \







|
|







3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
	(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 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
	(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_InitStringRep \
	(tclStubsPtr->tcl_InitStringRep) /* 637 */
#define Tcl_FetchIntRep \
	(tclStubsPtr->tcl_FetchIntRep) /* 638 */
#define Tcl_StoreIntRep \
	(tclStubsPtr->tcl_StoreIntRep) /* 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 */
















































































#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */


#if defined(USE_TCL_STUBS)

#   undef Tcl_CreateInterp
#   undef Tcl_Init
#   undef Tcl_ObjSetVar2
#   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_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)
#define Tcl_GlobalEval(interp, objPtr) \
	Tcl_EvalEx(interp, objPtr, -1, 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(__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.







|
|


|
|
|
|


















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>
|
>
|
|
|
<
<
<
<
<
<
<
<
<
<
<














|
|
|
|
|
|



















|

|

<
<
<
<
<
<
<
<
<
<
<
<
<
<














|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	(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_FreeInternalRep \
	(tclStubsPtr->tcl_FreeInternalRep) /* 636 */
#define Tcl_InitStringRep \
	(tclStubsPtr->tcl_InitStringRep) /* 637 */
#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 */
/* Slot 657 is reserved */
#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 TclUnusedStubEntry \
	(tclStubsPtr->tclUnusedStubEntry) /* 688 */

#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */

#undef TclUnusedStubEntry

#ifdef _WIN32
#   undef Tcl_CreateFileHandler
#   undef Tcl_DeleteFileHandler
#   undef Tcl_GetOpenFile











#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(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, TCL_INDEX_NONE, 0)
#define Tcl_GlobalEval(interp, objPtr) \
	Tcl_EvalEx(interp, objPtr, TCL_INDEX_NONE, TCL_EVAL_GLOBAL)
#define Tcl_GetStringResult(interp) Tcl_GetString(Tcl_GetObjResult(interp))














#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)
#   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
	    int intValue;
	    int result = tclStubsPtr->tcl_ExprLongObj(interp, obj, (long *)&intValue);
	    if (result == TCL_OK) *ptr = (long)intValue;
	    return result;
	}
#   endif
#endif






































#ifdef TCL_MEM_DEBUG
#   undef Tcl_Alloc
#   define Tcl_Alloc(x) \
    (Tcl_DbCkalloc((x), __FILE__, __LINE__))
#   undef Tcl_Free
#   define Tcl_Free(x) \







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    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
#ifdef __GNUC__
	/* 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
#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) \
	(TCLBOOLWARNING(boolPtr)(sizeof(*(boolPtr)) >= sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? tclStubsPtr->tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \
	Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
#define Tcl_GetBoolean(interp, src, boolPtr) \
	(TCLBOOLWARNING(boolPtr)(sizeof(*(boolPtr)) >= sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? tclStubsPtr->tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \
	Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
#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) \
	(TCLBOOLWARNING(boolPtr)(sizeof(*(boolPtr)) >= sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? Tcl_GetBooleanFromObj(interp, objPtr, (int *)(boolPtr)) : \
	Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
#define Tcl_GetBoolean(interp, src, boolPtr) \
	(TCLBOOLWARNING(boolPtr)(sizeof(*(boolPtr)) >= sizeof(int) && (TCL_MAJOR_VERSION == 8)) ? Tcl_GetBoolean(interp, src, (int *)(boolPtr)) : \
	Tcl_GetBool(interp, src, (TCL_NULL_OK-2)&(int)sizeof((*(boolPtr))), (char *)(boolPtr)))
#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
#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
#   undef Tcl_UniCharToUtfDString
#   define Tcl_UniCharToUtfDString Tcl_Char16ToUtfDString
#   undef Tcl_UtfToUniCharDString
#   define Tcl_UtfToUniCharDString Tcl_UtfToChar16DString
#   undef Tcl_UtfToUniChar
#   define Tcl_UtfToUniChar Tcl_UtfToChar16
























#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)
#   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)
#   define Tcl_UtfToWChar (sizeof(wchar_t) != sizeof(short) \
		? (int (*)(const char *, wchar_t *))tclStubsPtr->tcl_UtfToChar16 \
		: (int (*)(const char *, wchar_t *))Tcl_UtfToUniChar)



#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)
#   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)
#   define Tcl_UtfToWChar (sizeof(wchar_t) != sizeof(short) \
		? (int (*)(const char *, wchar_t *))Tcl_UtfToChar16 \
		: (int (*)(const char *, wchar_t *))Tcl_UtfToUniChar)



#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
#	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_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)

#if defined(USE_TCL_STUBS) && (TCL_UTF_MAX <= 3)
#   undef Tcl_UtfCharComplete
#   define Tcl_UtfCharComplete(src, length) (((unsigned)((unsigned char)*(src) - 0xF0) < 5) \
	    ? ((length) >= TCL_UTF_MAX) : tclStubsPtr->tcl_UtfCharComplete((src), (length)))
#endif
#ifndef TCL_NO_DEPRECATED
#   define Tcl_CreateSlave Tcl_CreateChild
#   define Tcl_GetSlave Tcl_GetChild
#   define Tcl_GetMaster Tcl_GetParent
#endif
















































































































































#endif /* _TCLDECLS */







<



|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|

|
|

|
|
>
>
>


|
|

|
|

|
|
>
>
>











<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<


<
|
<
|
<
<
|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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
#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_BackgroundError(interp)	Tcl_BackgroundException((interp), TCL_ERROR)
#define Tcl_StringMatch(str, pattern) Tcl_StringCaseMatch((str), (pattern), 0)

#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 *, 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 *, 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) \
		? (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 *, 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 *, Tcl_Size, Tcl_DString *))Tcl_UtfToUniCharDString \
		: (wchar_t *(*)(const char *, Tcl_Size, Tcl_DString *))Tcl_UtfToChar16DString)
#   define Tcl_UtfToWChar (sizeof(wchar_t) != sizeof(short) \
		? (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 TCL_MAJOR_VERSION > 8
#   undef Tcl_Close




















#   define Tcl_Close(interp, chan) Tcl_CloseEx(interp, chan, 0)










#endif


#undef TclUtfCharComplete

#undef TclUtfNext


#undef TclUtfPrev
#ifndef TCL_NO_DEPRECATED
#   define Tcl_CreateSlave Tcl_CreateChild
#   define Tcl_GetSlave Tcl_GetChild
#   define Tcl_GetMaster Tcl_GetParent
#endif

/* Protect those 10 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

#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))
#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
#   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)))
#   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)))
#   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
/*
 * 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.
 *
 * 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"






|







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 © 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"
57
58
59
60
61
62
63


64
65
66
67
68
69
70
					Tcl_Obj *keyPtr);
static Tcl_NRPostProc		FinalizeDictUpdate;
static Tcl_NRPostProc		FinalizeDictWith;
static Tcl_ObjCmdProc		DictForNRCmd;
static Tcl_ObjCmdProc		DictMapNRCmd;
static Tcl_NRPostProc		DictForLoopCallback;
static Tcl_NRPostProc		DictMapLoopCallback;



/*
 * Table of dict subcommand names and implementations.
 */

static const EnsembleImplMap implementationMap[] = {
    {"append",	DictAppendCmd,	TclCompileDictAppendCmd, NULL, NULL, 0 },







>
>







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
					Tcl_Obj *keyPtr);
static Tcl_NRPostProc		FinalizeDictUpdate;
static Tcl_NRPostProc		FinalizeDictWith;
static Tcl_ObjCmdProc		DictForNRCmd;
static Tcl_ObjCmdProc		DictMapNRCmd;
static Tcl_NRPostProc		DictForLoopCallback;
static Tcl_NRPostProc		DictMapLoopCallback;
static Tcl_ObjTypeLengthProc    DictAsListLength;
/* static Tcl_ObjTypeIndexProc     DictAsListIndex; Needs rewrite */

/*
 * Table of dict subcommand names and implementations.
 */

static const EnsembleImplMap implementationMap[] = {
    {"append",	DictAppendCmd,	TclCompileDictAppendCmd, NULL, NULL, 0 },
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149












150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
				 * dictionary. Used for doing traversal of the
				 * entries in the order that they are
				 * created. */
    ChainEntry *entryChainTail;	/* Other end of linked list of all entries in
				 * the dictionary. Used for doing traversal of
				 * the entries in the order that they are
				 * created. */
    size_t epoch;		/* Epoch counter */
    size_t refCount;		/* Reference counter (see above) */
    Tcl_Obj *chain;		/* Linked list used for invalidating the
				 * string representations of updated nested
				 * dictionaries. */
} Dict;

/*
 * 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 */












};

#define DictSetIntRep(objPtr, dictRepPtr)				\
    do {                                                                \
        Tcl_ObjIntRep ir;                                               \
        ir.twoPtrValue.ptr1 = (dictRepPtr);                             \
        ir.twoPtrValue.ptr2 = NULL;                                     \
        Tcl_StoreIntRep((objPtr), &tclDictType, &ir);                   \
    } while (0)

#define DictGetIntRep(objPtr, dictRepPtr)				\
    do {                                                                \
        const Tcl_ObjIntRep *irPtr;                                     \
        irPtr = TclFetchIntRep((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,
    TclHashObjKey,
    TclCompareObjKeys,
    AllocChainEntry,
    TclFreeObjEntry
};

/*







|













|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>


|

|


|


|

|
|















|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
				 * dictionary. Used for doing traversal of the
				 * entries in the order that they are
				 * created. */
    ChainEntry *entryChainTail;	/* Other end of linked list of all entries in
				 * the dictionary. Used for doing traversal of
				 * the entries in the order that they are
				 * created. */
    size_t epoch; 	/* Epoch counter */
    size_t refCount;		/* Reference counter (see above) */
    Tcl_Obj *chain;		/* Linked list used for invalidating the
				 * string representations of updated nested
				 * dictionaries. */
} Dict;

/*
 * 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 */
    TCL_OBJTYPE_V2(		/* Extended type for AbstractLists */
    DictAsListLength,		/* return "list" length of dict value w/o
				 * shimmering */
    NULL,			/* return key or value at "list" index
				 * location.  (keysare at even indicies,
				 * values at odd indicies) */
    NULL,
    NULL,
    NULL,
    NULL,
    NULL,
    NULL)
};

#define DictSetInternalRep(objPtr, dictRepPtr)				\
    do {                                                                \
        Tcl_ObjInternalRep ir;                                               \
        ir.twoPtrValue.ptr1 = (dictRepPtr);                             \
        ir.twoPtrValue.ptr2 = NULL;                                     \
        Tcl_StoreInternalRep((objPtr), &tclDictType, &ir);                   \
    } while (0)

#define DictGetInternalRep(objPtr, dictRepPtr)				\
    do {                                                                \
        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,
    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
DupDictInternalRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *copyPtr)
{
    Dict *oldDict, *newDict = (Dict *)Tcl_Alloc(sizeof(Dict));
    ChainEntry *cPtr;

    DictGetIntRep(srcPtr, oldDict);

    /*
     * Copy values across from the old hash table.
     */

    InitChainTable(newDict);
    for (cPtr=oldDict->entryChainHead ; cPtr!=NULL ; cPtr=cPtr->nextPtr) {







|







372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
DupDictInternalRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *copyPtr)
{
    Dict *oldDict, *newDict = (Dict *)Tcl_Alloc(sizeof(Dict));
    ChainEntry *cPtr;

    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
    newDict->chain = NULL;
    newDict->refCount = 1;

    /*
     * Store in the object.
     */

    DictSetIntRep(copyPtr, newDict);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeDictInternalRep --
 *







|







405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
    newDict->chain = NULL;
    newDict->refCount = 1;

    /*
     * Store in the object.
     */

    DictSetInternalRep(copyPtr, newDict);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeDictInternalRep --
 *
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432

static void
FreeDictInternalRep(
    Tcl_Obj *dictPtr)
{
    Dict *dict;

    DictGetIntRep(dictPtr, dict);

    if (dict->refCount-- <= 1) {
	DeleteDict(dict);
    }
}

/*







|







432
433
434
435
436
437
438
439
440
441
442
443
444
445
446

static void
FreeDictInternalRep(
    Tcl_Obj *dictPtr)
{
    Dict *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
    Tcl_Obj *dictPtr)
{
#define LOCAL_SIZE 64
    char localFlags[LOCAL_SIZE], *flagPtr = NULL;
    Dict *dict;
    ChainEntry *cPtr;
    Tcl_Obj *keyPtr, *valuePtr;

    size_t i, length, 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;

    DictGetIntRep(dictPtr, dict);

    assert (dict != NULL);

    numElems = dict->table.numEntries * 2;

    /* Handle empty list case first, simplifies what follows */
    if (numElems == 0) {







>
|








|

|







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
    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 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...
     */

    Tcl_Size numElems;

    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

	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++ = ' ';
    }

    (void)Tcl_InitStringRep(dictPtr, NULL, bytesNeeded - 1);

    if (flagPtr != localFlags) {
	Tcl_Free(flagPtr);
    }
}








>







567
568
569
570
571
572
573
574
575
576
577
578
579
580
581

	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

    /*
     * 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;
	Tcl_Obj **objv;

	/* Cannot fail, we already know the Tcl_ObjType is "list". */
	TclListObjGetElements(NULL, objPtr, &objc, &objv);
	if (objc & 1) {
	    goto missingValue;
	}







|
|







612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

    /*
     * 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 (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

		TclDecrRefCount(discardedValue);
	    }
	    Tcl_SetHashValue(hPtr, objv[i+1]);
	    Tcl_IncrRefCount(objv[i+1]); /* Since hash now holds ref to it */
	}
    } else {
	size_t 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;
	    int literal;

	    if (TclFindDictElement(interp, nextElem, (limit - nextElem),
		    &elemStart, &nextElem, &elemSize, &literal) != TCL_OK) {
		goto errorInFindDictElement;
	    }
	    if (elemStart == limit) {







|






|







643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

		TclDecrRefCount(discardedValue);
	    }
	    Tcl_SetHashValue(hPtr, objv[i+1]);
	    Tcl_IncrRefCount(objv[i+1]); /* Since hash now holds ref to it */
	}
    } else {
	Tcl_Size length;
	const char *nextElem = TclGetStringFromObj(objPtr, &length);
	const char *limit = (nextElem + length);

	while (nextElem < limit) {
	    Tcl_Obj *keyPtr, *valuePtr;
	    const char *elemStart;
	    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
     * 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);
    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);
    }
  errorInFindDictElement:
    DeleteChainTable(dict);
    Tcl_Free(dict);
    return TCL_ERROR;
}

static Dict *
GetDictFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr)
{
    Dict *dict;

    DictGetIntRep(dictPtr, dict);
    if (dict == NULL) {
	if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
	    return NULL;
	}
	DictGetIntRep(dictPtr, dict);
    }
    return dict;
}

/*
 *----------------------------------------------------------------------
 *







|






|














|




|







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
     * 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;
    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", (void *)NULL);
    }
  errorInFindDictElement:
    DeleteChainTable(dict);
    Tcl_Free(dict);
    return TCL_ERROR;
}

static Dict *
GetDictFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr)
{
    Dict *dict;

    DictGetInternalRep(dictPtr, dict);
    if (dict == NULL) {
	if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
	    return NULL;
	}
	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
 *	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
 *	dictionary, resulting in the path being built.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclTraceDictPath(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int keyc,
    Tcl_Obj *const keyv[],
    int flags)
{
    Dict *dict, *newDict;
    int i;

    DictGetIntRep(dictPtr, dict);
    if (dict == NULL) {
	if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
	    return NULL;
	}
	DictGetIntRep(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]);







|









|




|

|




|







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
 *	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-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,
    Tcl_Size keyc,
    Tcl_Obj *const keyv[],
    int flags)
{
    Dict *dict, *newDict;
    Tcl_Size i;

    DictGetInternalRep(dictPtr, dict);
    if (dict == NULL) {
	if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
	    return NULL;
	}
	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
	    }
	    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);
		}
		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);

	    if (newDict == NULL) {
		if (SetDictFromAny(interp, tmpObj) != TCL_OK) {
		    return NULL;
		}
	    }
	}

	DictGetIntRep(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);
	    }

	    newDict->chain = dictPtr;
	}
	dict = newDict;
	dictPtr = tmpObj;
    }
    return dictPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * InvalidateDictChain --
 *
 *	Go through a dictionary chain (built by an updating invokation 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);
    assert( dict != NULL);

    do {
	dict->refCount++;
	TclInvalidateStringRep(dictObj);
	TclFreeIntRep(dictObj);
	DictSetIntRep(dictObj, dict);

	dict->epoch++;
	dictObj = dict->chain;
	if (dictObj == NULL) {
	    break;
	}
	dict->chain = NULL;
	DictGetIntRep(dictObj, dict);
    } while (dict != NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DictObjPut --







|















|








|







|















|




















|





|
|







|







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
	    }
	    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]), (void *)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);

	    DictGetInternalRep(tmpObj, newDict);

	    if (newDict == NULL) {
		if (SetDictFromAny(interp, tmpObj) != TCL_OK) {
		    return NULL;
		}
	    }
	}

	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++;
		DictGetInternalRep(tmpObj, newDict);
	    }

	    newDict->chain = dictPtr;
	}
	dict = newDict;
	dictPtr = tmpObj;
    }
    return dictPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * InvalidateDictChain --
 *
 *	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;

    DictGetInternalRep(dictObj, dict);
    assert( dict != NULL);

    do {
	dict->refCount++;
	TclInvalidateStringRep(dictObj);
	TclFreeInternalRep(dictObj);
	DictSetInternalRep(dictObj, dict);

	dict->epoch++;
	dictObj = dict->chain;
	if (dictObj == NULL) {
	    break;
	}
	dict->chain = NULL;
	DictGetInternalRep(dictObj, dict);
    } while (dict != NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DictObjPut --
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
    if (dict == NULL) {
	return TCL_ERROR;
    }

    TclInvalidateStringRep(dictPtr);
    hPtr = CreateChainEntry(dict, keyPtr, &isNew);
    dict->refCount++;
    TclFreeIntRep(dictPtr)
    DictSetIntRep(dictPtr, dict);
    Tcl_IncrRefCount(valuePtr);
    if (!isNew) {
	Tcl_Obj *oldValuePtr = (Tcl_Obj *)Tcl_GetHashValue(hPtr);

	TclDecrRefCount(oldValuePtr);
    }
    Tcl_SetHashValue(hPtr, valuePtr);







|
|







953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
    if (dict == NULL) {
	return TCL_ERROR;
    }

    TclInvalidateStringRep(dictPtr);
    hPtr = CreateChainEntry(dict, keyPtr, &isNew);
    dict->refCount++;
    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
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *




















 * 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.
 *
 *----------------------------------------------------------------------
 */


int
Tcl_DictObjSize(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int *sizePtr)
{
    Dict *dict;

    dict = GetDictFromObj(interp, dictPtr);
    if (dict == NULL) {
	return TCL_ERROR;
    }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















>




|







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
    }
    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,
    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
				 * 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 (!searchPtr->epoch) {
	*donePtr = 1;
	return;
    }








|







1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
				 * written into when there are no further
				 * values in the dictionary, or a 0
				 * otherwise. */
{
    ChainEntry *cPtr;

    /*
     * 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
 *----------------------------------------------------------------------
 */

int
Tcl_DictObjPutKeyList(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int 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);
    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);







|



















|







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
 *----------------------------------------------------------------------
 */

int
Tcl_DictObjPutKeyList(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    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;
    }

    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
 *----------------------------------------------------------------------
 */

int
Tcl_DictObjRemoveKeyList(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int 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);
    assert(dict != NULL);
    DeleteChainEntry(dict, keyv[keyc-1]);
    InvalidateDictChain(dictPtr);
    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
1401
1402
 *----------------------------------------------------------------------
 */

int
Tcl_DictObjRemoveKeyList(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    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;
    }

    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
    TclNewObj(dictPtr);
    TclInvalidateStringRep(dictPtr);
    dict = (Dict *)Tcl_Alloc(sizeof(Dict));
    InitChainTable(dict);
    dict->epoch = 1;
    dict->chain = NULL;
    dict->refCount = 1;
    DictSetIntRep(dictPtr, dict);
    return dictPtr;
#endif
}

/*
 *----------------------------------------------------------------------
 *







|







1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
    TclNewObj(dictPtr);
    TclInvalidateStringRep(dictPtr);
    dict = (Dict *)Tcl_Alloc(sizeof(Dict));
    InitChainTable(dict);
    dict->epoch = 1;
    dict->chain = NULL;
    dict->refCount = 1;
    DictSetInternalRep(dictPtr, dict);
    return dictPtr;
#endif
}

/*
 *----------------------------------------------------------------------
 *
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
    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);
    return dictPtr;
}
#else /* !TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_DbNewDictObj(
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)







|







1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
    TclDbNewObj(dictPtr, file, line);
    TclInvalidateStringRep(dictPtr);
    dict = (Dict *)Tcl_Alloc(sizeof(Dict));
    InitChainTable(dict);
    dict->epoch = 1;
    dict->chain = NULL;
    dict->refCount = 1;
    DictSetInternalRep(dictPtr, dict);
    return dictPtr;
}
#else /* !TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_DbNewDictObj(
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictCreateCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictObj;
    int i;








|







1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictCreateCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictGetCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *valuePtr = NULL;
    int result;








|







1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictGetCmd(
    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
	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);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, valuePtr);
    return TCL_OK;
}

/*







|







1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
	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]), (void *)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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictGetDefCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *keyPtr, *valuePtr, *defaultPtr;
    Tcl_Obj *const *keyPath;
    int numKeys;







|







1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictGetDefCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictReplaceCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr;
    int i;








|







1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictReplaceCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictRemoveCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr;
    int i;








|







1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictRemoveCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictMergeCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *targetObj, *keyObj = NULL, *valueObj = NULL;
    int allocatedDict = 0;
    int i, done;







|







1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictMergeCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictKeysCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *listPtr;
    const char *pattern = NULL;








|







1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictKeysCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictValuesCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *valuePtr = NULL, *listPtr;
    Tcl_DictSearch search;
    int done;







|







1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictValuesCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictSizeCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int result, 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;
}

/*
 *----------------------------------------------------------------------
 *
 * DictExistsCmd --







|




|
>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictSizeCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictExistsCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *valuePtr;

    if (objc < 3) {







|







2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictExistsCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictInfoCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Dict *dict;
    char *statsStr;








|







2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictInfoCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictIncrCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int code = TCL_OK;
    Tcl_Obj *dictPtr, *valuePtr = NULL;








|







2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictIncrCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictLappendCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
    int i, allocatedDict = 0, allocatedValue = 0;








|







2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictLappendCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictAppendCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *valuePtr, *resultPtr;
    int allocatedDict = 0;








|







2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictAppendCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictForNRCmd(
    TCL_UNUSED(ClientData),
    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;

    int varc, 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);
	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;







|








>
|

















|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictForNRCmd(
    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 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", (void *)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
    Tcl_DictObjDone(searchPtr);
    TclStackFree(interp, searchPtr);
    return TCL_ERROR;
}

static int
DictForLoopCallback(
    ClientData 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];







|







2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
    Tcl_DictObjDone(searchPtr);
    TclStackFree(interp, searchPtr);
    return TCL_ERROR;
}

static int
DictForLoopCallback(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictMapNRCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj **varv, *keyObj, *valueObj;
    DictMapStorage *storagePtr;

    int varc, 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);
	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;







|







>
|

















|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictMapNRCmd(
    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 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", (void *)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
    Tcl_DictObjDone(&storagePtr->search);
    TclStackFree(interp, storagePtr);
    return TCL_ERROR;
}

static int
DictMapLoopCallback(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    DictMapStorage *storagePtr = (DictMapStorage *)data[0];
    Tcl_Obj *keyObj, *valueObj;
    int done;







|







2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
    Tcl_DictObjDone(&storagePtr->search);
    TclStackFree(interp, storagePtr);
    return TCL_ERROR;
}

static int
DictMapLoopCallback(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictSetCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *resultPtr;
    int result, allocatedDict = 0;








|







2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictSetCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictUnsetCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *dictPtr, *resultPtr;
    int result, allocatedDict = 0;








|







3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictUnsetCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictFilterCmd(
    TCL_UNUSED(ClientData),
    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
    };
    Tcl_Obj *scriptObj, *keyVarObj, *valueVarObj;
    Tcl_Obj **varv, *keyObj = NULL, *valueObj = NULL, *resultObj, *boolObj;
    Tcl_DictSearch search;
    int index, varc, done, result, satisfied;

    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) {
    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) {







|










|



|
>











|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictFilterCmd(
    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 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 (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

	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);
	    return TCL_ERROR;
	}
	keyVarObj = varv[0];
	valueVarObj = varv[1];
	scriptObj = objv[4];

	/*







|







3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214

	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", (void *)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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictUpdateCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *dictPtr, *objPtr;
    int i, dummy;


    if (objc < 5 || !(objc & 1)) {
	Tcl_WrongNumArgs(interp, 1, objv,
		"dictVarName key varName ?key varName ...? script");
	return TCL_ERROR;
    }








|






|
>







3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictUpdateCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *dictPtr, *objPtr;
    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
    TclNRAddCallback(interp, FinalizeDictUpdate, objv[1], objPtr, NULL,NULL);

    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictUpdate(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *dictPtr, *objPtr, **objv;
    Tcl_InterpState state;
    int i, objc;
    Tcl_Obj *varName = (Tcl_Obj *)data[0];
    Tcl_Obj *argsObj = (Tcl_Obj *)data[1];

    /*
     * ErrorInfo handling.
     */








|





|







3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
    TclNRAddCallback(interp, FinalizeDictUpdate, objv[1], objPtr, NULL,NULL);

    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictUpdate(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj *dictPtr, *objPtr, **objv;
    Tcl_InterpState state;
    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
    }

    /*
     * Write back the values from the variables, treating failure to read as
     * an instruction to remove the key.
     */

    Tcl_ListObjGetElements(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







|







3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
    }

    /*
     * Write back the values from the variables, treating failure to read as
     * an instruction to remove the key.
     */

    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictWithCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *dictPtr, *keysPtr, *pathPtr;








|







3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
DictWithCmd(
    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
	    NULL);

    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictWith(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj **pathv;
    int 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);
    } else {
	pathc = 0;
	pathv = NULL;
    }

    /*
     * Pack from local variables back into the dictionary.







|




|

















|







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
	    NULL);

    return TclNREvalObjEx(interp, objv[objc-1], 0, iPtr->cmdFramePtr, objc-1);
}

static int
FinalizeDictWith(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj **pathv;
    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) {
	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
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclDictWithInit(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    int pathc,
    Tcl_Obj *const pathv[])
{
    Tcl_DictSearch s;
    Tcl_Obj *keyPtr, *valPtr, *keysPtr;
    int done;

    if (pathc > 0) {







|







3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclDictWithInit(
    Tcl_Interp *interp,
    Tcl_Obj *dictPtr,
    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
    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_Obj **keyv;

    /*
     * If the dictionary variable doesn't exist, drop everything silently.
     */

    dictPtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr, part1Ptr, part2Ptr,







|







3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
    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;
    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
    } 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
	 * 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) {







|
|
|







3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
    } else {
	allocdict = 0;
    }

    if (pathc > 0) {
	/*
	 * Want to get to the dictionary which we will update; need to do
	 * 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) {
3755
3756
3757
3758
3759
3760
3761
3762

























































































































































3763
3764
3765
3766
3767
3768
Tcl_Command
TclInitDictCmd(
    Tcl_Interp *interp)
{
    return TclMakeEnsemble(interp, "dict", implementationMap);
}

/*

























































































































































 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






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
Tcl_Command
TclInitDictCmd(
    Tcl_Interp *interp)
{
    return TclMakeEnsemble(interp, "dict", implementationMap);
}

/*
 *----------------------------------------------------------------------
 *
 * DictAsListLength --
 *
 *   Compute the length of a list as if the dict value were converted to a
 *   list.
 *
 *   Note: the list length may not match the dict size * 2.  This occurs when
 *   there are duplicate keys in the original string representation.
 *
 * Side Effects --
 *
 *   The intent is to have no side effects.
 */

static Tcl_Size
DictAsListLength(
    Tcl_Obj *objPtr)
{
    Tcl_Size estCount, length, llen;
    const char *limit, *nextElem = TclGetStringFromObj(objPtr, &length);
    Tcl_Obj *elemPtr;

    /*
     * 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. */
    elemPtr = Tcl_NewObj();

    llen = 0;

    while (nextElem < limit) {
	const char *elemStart;
	char *check;
	Tcl_Size elemSize;
	int literal;

	if (TCL_OK != TclFindElement(NULL, nextElem, limit - nextElem,
		&elemStart, &nextElem, &elemSize, &literal)) {
	    Tcl_DecrRefCount(elemPtr);
	    return 0;
	}
	if (elemStart == limit) {
	    break;
	}

	TclInvalidateStringRep(elemPtr);
	check = Tcl_InitStringRep(elemPtr, literal ? elemStart : NULL,
		elemSize);
	if (elemSize && check == NULL) {
	    Tcl_DecrRefCount(elemPtr);
	    return 0;
	}
	if (!literal) {
	    Tcl_InitStringRep(elemPtr, NULL,
		    TclCopyAndCollapse(elemSize, elemStart, check));
	}
	llen++;
    }
    Tcl_DecrRefCount(elemPtr);
    return llen;
}


/*
 *----------------------------------------------------------------------
 *
 * DictAsListIndex --
 *
 *   Return the key or value at the given "list" index, i.e., as if the string
 *   value where treated as a list. The intent is to support this list
 *   operation w/o causing the Obj value to shimmer into a List.
 *
 * Side Effects --
 *
 *   The intent is to have no side effects.
 *
 */
#if 0 /* Needs rewrite */
static int
DictAsListIndex(
    Tcl_Interp *interp,
    struct Tcl_Obj *objPtr,
    Tcl_Size index,
    Tcl_Obj** elemObjPtr)
{
    Tcl_Size /*estCount,*/ length, llen;
    const char *limit, *nextElem = TclGetStringFromObj(objPtr, &length);
    Tcl_Obj *elemPtr;

    /*
     * Compute limit of the list string
     */

    TclMaxListLength(nextElem, length, &limit);
    elemPtr = Tcl_NewObj();

    llen = 0;

    /*
     * parse out each element until reaching the "index"th element.
     * Sure this is slow, but shimmering is slower.
     */
    while (nextElem < limit) {
	const char *elemStart;
	char *check;
	Tcl_Size elemSize;
	int literal;

	if (TCL_OK != TclFindElement(NULL, nextElem, limit - nextElem,
		&elemStart, &nextElem, &elemSize, &literal)) {
	    Tcl_DecrRefCount(elemPtr);
	    return 0;
	}
	if (elemStart == limit) {
	    break;
	}

	TclInvalidateStringRep(elemPtr);
	check = Tcl_InitStringRep(elemPtr, literal ? elemStart : NULL,
		elemSize);
	if (elemSize && check == NULL) {
	    Tcl_DecrRefCount(elemPtr);
	    if (interp) {
		// Need error message here
	    }
	    return TCL_ERROR;
	}
	if (!literal) {
	    Tcl_InitStringRep(elemPtr, NULL,
		    TclCopyAndCollapse(elemSize, elemStart, check));
	}
	if (llen == index) {
	    *elemObjPtr = elemPtr;
	    return TCL_OK;
	}
	llen++;
    }

    /*
     * Index is beyond end of list - return empty
     */
    Tcl_InitStringRep(elemPtr, NULL, 0);
    *elemObjPtr = elemPtr;
    return TCL_OK;
}
#endif

/*
 * 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
/*
 * 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.
 *
 * 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"






|
|
|







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 © 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
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);
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 */

};

#define InstNameSetIntRep(objPtr, inst)				\
    do {							\
	Tcl_ObjIntRep ir;					\
	ir.wideValue = (inst);					\
	Tcl_StoreIntRep((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;			\
    } while (0)


/*
 *----------------------------------------------------------------------
 *
 * GetLocationInformation --







|













>


|

|

|


|

|
|

|







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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 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, 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 InstNameSetInternalRep(objPtr, inst)				\
    do {							\
	Tcl_ObjInternalRep ir;					\
	ir.wideValue = (inst);					\
	Tcl_StoreInternalRep((objPtr), &instNameType, &ir);		\
    } while (0)

#define InstNameGetInternalRep(objPtr, inst)				\
    do {							\
	const Tcl_ObjInternalRep *irPtr;				\
	irPtr = TclFetchInternalRep((objPtr), &instNameType);	\
	assert(irPtr != NULL);					\
	(inst) = irPtr->wideValue;			\
    } while (0)


/*
 *----------------------------------------------------------------------
 *
 * GetLocationInformation --
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
 */

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. */
{
    char *bytes;
    size_t length;

    bytes = TclGetStringFromObj(objPtr, &length);
    TclPrintSource(outFile, bytes, TclMin(length, maxChars));
}

/*
 *----------------------------------------------------------------------







|


|







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
 */

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. */
    Tcl_Size maxChars)		/* Maximum number of chars to print. */
{
    char *bytes;
    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
 *----------------------------------------------------------------------
 */

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_Obj *bufferObj;

    TclNewObj(bufferObj);
    PrintSourceToObj(bufferObj, stringPtr, maxChars);
    fprintf(outFile, "%s", TclGetString(bufferObj));
    Tcl_DecrRefCount(bufferObj);







|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
 *----------------------------------------------------------------------
 */

void
TclPrintSource(
    FILE *outFile,		/* The file to print the source to. */
    const char *stringPtr,	/* The string 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
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;

    Interp *iPtr;
    Tcl_Obj *bufferObj, *fileObj;

    ByteCodeGetIntRep(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",
	    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",
	    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)),
	    codePtr->numCodeBytes,
	    (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
	    (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)),
	    (unsigned long) (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_AppendPrintfToObj(bufferObj,
		"  Proc %p, refCt %" TCL_Z_MODIFIER "u, args %d, compiled locals %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,
			(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)) {







|
>



|

















|










|











|
>
|
|

|
|
|











|


|







|







252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
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, line;
    Tcl_Size i;
    Interp *iPtr;
    Tcl_Obj *bufferObj, *fileObj;

    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_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 %" 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 %" 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,
	    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;
	Tcl_Size numCompiledLocals = procPtr->numCompiledLocals;

	Tcl_AppendPrintfToObj(bufferObj,
		"  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 %" 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
	}
    }

    /*
     * Print the ExceptionRange array.
     */

    if (codePtr->numExceptRanges > 0) {
	Tcl_AppendPrintfToObj(bufferObj, "  Exception ranges %d, depth %d:\n",
		codePtr->numExceptRanges, codePtr->maxExceptDepth);
	for (i = 0;  i < codePtr->numExceptRanges;  i++) {
	    ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i];

	    Tcl_AppendPrintfToObj(bufferObj,
		    "      %d: level %d, %s, pc %d-%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",
			rangePtr->continueOffset, rangePtr->breakOffset);
		break;
	    case CATCH_EXCEPTION_RANGE:
		Tcl_AppendPrintfToObj(bufferObj, "catch %d\n",
			rangePtr->catchOffset);
		break;
	    default:
		Tcl_Panic("DisassembleByteCodeObj: bad ExceptionRange type %d",
			rangePtr->type);
	    }
	}







|
|

|



|






|



|







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
	}
    }

    /*
     * Print the ExceptionRange array.
     */

    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 < (int)codePtr->numExceptRanges;  i++) {
	    ExceptionRange *rangePtr = &codePtr->exceptArrayPtr[i];

	    Tcl_AppendPrintfToObj(bufferObj,
		    "      %" 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 %" TCL_SIZE_MODIFIER "d, break %" TCL_SIZE_MODIFIER "d\n",
			rangePtr->continueOffset, rangePtr->breakOffset);
		break;
	    case CATCH_EXCEPTION_RANGE:
		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
	    srcLen = TclGetInt4AtPtr(srcLengthNext);
	    srcLengthNext += 4;
	} else {
	    srcLen = TclGetInt1AtPtr(srcLengthNext);
	    srcLengthNext++;
	}

	Tcl_AppendPrintfToObj(bufferObj, "%s%4d: 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);
    }







|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
	    srcLen = TclGetInt4AtPtr(srcLengthNext);
	    srcLengthNext += 4;
	} else {
	    srcLen = TclGetInt1AtPtr(srcLengthNext);
	    srcLengthNext++;
	}

	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
	 */

	while ((pc-codeStart) < codeOffset) {
	    Tcl_AppendToObj(bufferObj, "    ", -1);
	    pc += FormatInstruction(codePtr, pc, bufferObj);
	}

	Tcl_AppendPrintfToObj(bufferObj, "  Command %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.







|







501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
	 */

	while ((pc-codeStart) < codeOffset) {
	    Tcl_AppendToObj(bufferObj, "    ", -1);
	    pc += FormatInstruction(codePtr, pc, bufferObj);
	}

	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
{
    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;
    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;








|







541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
{
    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;
    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
	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),
			", %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);
	    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);
	    } else {
		sprintf(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);







|






|





|

|







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
	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) {
		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++;
	    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) {
		snprintf(suffixBuffer, sizeof(suffixBuffer), "next cmd at pc %u", pcOffset+opnd);
	    } else {
		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
	    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)",
			    opnd, localCt);
		}
		for (j = 0;  j < opnd;  j++) {
		    localPtr = localPtr->nextPtr;
		}
		if (TclIsVarTemporary(localPtr)) {
		    sprintf(suffixBuffer, "temp var %u", opnd);
		} else {
		    sprintf(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_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) {







|






|

|

















|







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
	    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 (%" TCL_SIZE_MODIFIER "d locals)",
			    opnd, localCt);
		}
		for (j = 0;  j < opnd;  j++) {
		    localPtr = localPtr->nextPtr;
		}
		if (TclIsVarTemporary(localPtr)) {
		    snprintf(suffixBuffer, sizeof(suffixBuffer), "temp var %u", opnd);
		} else {
		    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;
	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

Tcl_Obj *
TclGetInnerContext(
    Tcl_Interp *interp,
    const unsigned char *pc,
    Tcl_Obj **tosPtr)
{
    int objc = 0, off = 0;
    Tcl_Obj *result;
    Interp *iPtr = (Interp *) interp;

    switch (*pc) {
    case INST_STR_LEN:
    case INST_LNOT:
    case INST_BITNOT:







|







687
688
689
690
691
692
693
694
695
696
697
698
699
700
701

Tcl_Obj *
TclGetInnerContext(
    Tcl_Interp *interp,
    const unsigned char *pc,
    Tcl_Obj **tosPtr)
{
    Tcl_Size objc = 0;
    Tcl_Obj *result;
    Interp *iPtr = (Interp *) interp;

    switch (*pc) {
    case INST_STR_LEN:
    case INST_LNOT:
    case INST_BITNOT:
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

    result = iPtr->innerContext;
    if (Tcl_IsShared(result)) {
        Tcl_DecrRefCount(result);
        iPtr->innerContext = result = Tcl_NewListObj(objc + 1, NULL);
        Tcl_IncrRefCount(result);
    } else {
        int len;

        /*
         * Reset while keeping the list intrep as much as possible.
         */

	Tcl_ListObjLength(interp, result, &len);
        Tcl_ListObjReplace(interp, result, 0, len, 0, NULL);
    }
    Tcl_ListObjAppendElement(NULL, result, TclNewInstNameObj(*pc));

    for (; objc>0 ; objc--) {
        Tcl_Obj *objPtr;

        objPtr = tosPtr[1 - objc + off];
        if (!objPtr) {
            Tcl_Panic("InnerContext: bad tos -- appending null object");
        }
        if ((objPtr->refCount<=0)
#ifdef TCL_MEM_DEBUG
                || (objPtr->refCount==0x61616161)
#endif
        ) {
            Tcl_Panic("InnerContext: bad tos -- appending freed object %p",
                    objPtr);
        }
        Tcl_ListObjAppendElement(NULL, result, objPtr);
    }







|


|


|







|



|

|







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

    result = iPtr->innerContext;
    if (Tcl_IsShared(result)) {
        Tcl_DecrRefCount(result);
        iPtr->innerContext = result = Tcl_NewListObj(objc + 1, NULL);
        Tcl_IncrRefCount(result);
    } else {
        Tcl_Size len;

        /*
         * Reset while keeping the list internalrep as much as possible.
         */

	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;

        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)
#endif
        ) {
            Tcl_Panic("InnerContext: bad tos -- appending freed object %p",
                    objPtr);
        }
        Tcl_ListObjAppendElement(NULL, result, objPtr);
    }
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
TclNewInstNameObj(
    unsigned char inst)
{
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    TclInvalidateStringRep(objPtr);
    InstNameSetIntRep(objPtr, (long) inst);

    return objPtr;
}

/*
 *----------------------------------------------------------------------
 *







|







806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
TclNewInstNameObj(
    unsigned char inst)
{
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    TclInvalidateStringRep(objPtr);
    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
static void
UpdateStringOfInstName(
    Tcl_Obj *objPtr)
{
    size_t inst;	/* NOTE: We know this is really an unsigned char */
    char *dst;

    InstNameGetIntRep(objPtr, inst);

    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);
	(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);
    }







|

|

|
|







828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
static void
UpdateStringOfInstName(
    Tcl_Obj *objPtr)
{
    size_t inst;	/* NOTE: We know this is really an unsigned char */
    char *dst;

    InstNameGetInternalRep(objPtr, inst);

    if (inst >= LAST_INST_OPCODE) {
	dst = Tcl_InitStringRep(objPtr, NULL, TCL_INTEGER_SPACE + 5);
	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
 *----------------------------------------------------------------------
 */

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. */
{
    const char *p;
    int 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);
	switch (ucs4) {
	case '"':
	    Tcl_AppendToObj(appendObj, "\\\"", -1);
	    i += 2;
	    continue;
	case '\f':
	    Tcl_AppendToObj(appendObj, "\\f", -1);







|


|











|







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
 *----------------------------------------------------------------------
 */

static void
PrintSourceToObj(
    Tcl_Obj *appendObj,		/* The object to print the source to. */
    const char *stringPtr,	/* The string to print. */
    Tcl_Size maxChars)		/* Maximum number of chars to print. */
{
    const char *p;
    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 = 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
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;

    ByteCodeGetIntRep(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;
	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))) {







|
|

|
















|







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
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, val, line;
    Tcl_Size i;

    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) {
	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
    }

    /*
     * Get the auxiliary data from the bytecode.
     */

    TclNewObj(aux);
    for (i=0 ; i<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);







|







1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
    }

    /*
     * Get the auxiliary data from the bytecode.
     */

    TclNewObj(aux);
    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);
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
    }

    /*
     * Get the exception ranges from the bytecode.
     */

    TclNewObj(exn);
    for (i=0 ; i<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",
		    "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",
		    "catch", rangePtr->nestingLevel, rangePtr->codeOffset,
		    rangePtr->codeOffset + rangePtr->numCodeBytes - 1,
		    rangePtr->catchOffset));
	    break;
	}
    }








|





|






|







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
    }

    /*
     * Get the exception ranges from the bytecode.
     */

    TclNewObj(exn);
    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 %" 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 %" 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

    TclNewObj(commands);
    codeOffPtr = codePtr->codeDeltaStart;
    codeLenPtr = codePtr->codeLengthStart;
    srcOffPtr = codePtr->srcDeltaStart;
    srcLenPtr = codePtr->srcLengthStart;
    codeOffset = sourceOffset = 0;
    for (i=0 ; i<codePtr->numCommands ; i++) {
	Tcl_Obj *cmd;

	codeOffset += Decode(codeOffPtr);
	codeLength = Decode(codeLenPtr);
	sourceOffset += Decode(srcOffPtr);
	sourceLength = Decode(srcLenPtr);
	TclNewObj(cmd);







|







1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191

    TclNewObj(commands);
    codeOffPtr = codePtr->codeDeltaStart;
    codeLenPtr = codePtr->codeLengthStart;
    srcOffPtr = codePtr->srcDeltaStart;
    srcLenPtr = codePtr->srcLengthStart;
    codeOffset = sourceOffset = 0;
    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);
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 order to disassemble them.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_DisassembleObjCmd(
    ClientData 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;
    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) {
    case DISAS_LAMBDA: {
	Command cmd;
	Tcl_Obj *nsObjPtr;
	Tcl_Namespace *nsPtr;

	/*
	 * Compile (if uncompiled) and disassemble a lambda term.







|












|
|















|







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
 *	in order to disassemble them.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_DisassembleObjCmd(
    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
    } 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 (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
	}

	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);
	    return TCL_ERROR;
	}

	/*
	 * Compile (if uncompiled) and disassemble a procedure.
	 */








|







1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
	}

	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]), (void *)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
	 */

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "script");
	    return TCL_ERROR;
	}

	if (!TclHasIntRep(objv[2], &tclByteCodeType) && (TCL_OK
		!= TclSetByteCodeFromAny(interp, objv[2], NULL, NULL))) {
	    return TCL_ERROR;
	}
	codeObjPtr = objv[2];
	break;

    case DISAS_CLASS_CONSTRUCTOR:







|







1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
	 */

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "script");
	    return TCL_ERROR;
	}

	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
	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);
	    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);
	    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);
	    return TCL_ERROR;
	}

	/*
	 * Compile if necessary.
	 */

	if (!TclHasIntRep(procPtr->bodyPtr, &tclByteCodeType)) {
	    Command cmd;

	    /*
	     * Yes, this is ugly, but we need to pass the namespace in to the
	     * compiler in two places.
	     */








|









|







|







|







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
	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]), (void *)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", (void *)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", (void *)NULL);
	    return TCL_ERROR;
	}

	/*
	 * Compile if necessary.
	 */

	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
	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);
	    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);
	    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);
	    return TCL_ERROR;
	}

	/*
	 * Compile if necessary.
	 */

	if (!TclHasIntRep(procPtr->bodyPtr, &tclByteCodeType)) {
	    Command cmd;

	    /*
	     * Yes, this is ugly, but we need to pass the namespace in to the
	     * compiler in two places.
	     */








|









|







|







|







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
	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]), (void *)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", (void *)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", (void *)NULL);
	    return TCL_ERROR;
	}

	/*
	 * Compile if necessary.
	 */

	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
	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);
	    return TCL_ERROR;
	}
	hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods,
		(char *) 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]);

	/*
	 * 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);
	    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);
	    return TCL_ERROR;
	}
	if (!TclHasIntRep(procPtr->bodyPtr, &tclByteCodeType)) {
	    Command cmd;

	    /*
	     * Yes, this is ugly, but we need to pass the namespace in to the
	     * compiler in two places.
	     */








|



|


















|











|







|


|







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
	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]), (void *)NULL);
	    return TCL_ERROR;
	}
	hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods,
		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, 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]), (void *)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", (void *)NULL);
	    return TCL_ERROR;
	}
	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
	CLANG_ASSERT(0);
    }

    /*
     * Do the actual disassembly.
     */

    ByteCodeGetIntRep(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);
	return TCL_ERROR;
    }
    if (clientData) {
	Tcl_SetObjResult(interp,
		DisassembleByteCodeAsDicts(codeObjPtr));
    } else {
	Tcl_SetObjResult(interp,







|





|







1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
	CLANG_ASSERT(0);
    }

    /*
     * Do the actual disassembly.
     */

    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", (void *)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
/*
 * tclEncoding.c --
 *
 *	Contains the implementation of the encoding conversion package.
 *
 * Copyright (c) 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"


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.
 */





|






>







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 © 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
				 * 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. */


    int 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. */
    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. */


    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







>
>
|



|
<
<





|
>
>







30
31
32
33
34
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. */
    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, 2, or 4. */


    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; 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
179
180
181
182
183
184
185




























186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241





242

243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
 * 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;





























/*
 * 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_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 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 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	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].
 */

static const Tcl_ObjType encodingType = {
    "encoding", FreeEncodingIntRep, DupEncodingIntRep, NULL, NULL





};

#define EncodingSetIntRep(objPtr, encoding)				\
    do {								\
	Tcl_ObjIntRep ir;						\
	ir.twoPtrValue.ptr1 = (encoding);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &encodingType, &ir);			\
    } while (0)

#define EncodingGetIntRep(objPtr, encoding)				\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep ((objPtr), &encodingType);		\
	(encoding) = irPtr ? (Tcl_Encoding)irPtr->twoPtrValue.ptr1 : NULL;		\
    } while (0)


/*
 *----------------------------------------------------------------------
 *







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













|





|













|
>
>
>



<
<
<
<
<
<
|
|
|
|



|




|
>
>
>
>
>

>
|

|


|


|

|
|







182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256






257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
 * 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	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	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		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 Tcl_EncodingConvertProc	UtfToUtfProc;
static Tcl_EncodingConvertProc	Iso88591FromUtfProc;
static Tcl_EncodingConvertProc	Iso88591ToUtfProc;


/*
 * 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",
    FreeEncodingInternalRep,
    DupEncodingInternalRep,
    NULL,
    NULL,
    TCL_OBJTYPE_V0
};

#define EncodingSetInternalRep(objPtr, encoding)				\
    do {								\
	Tcl_ObjInternalRep ir;						\
	ir.twoPtrValue.ptr1 = (encoding);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreInternalRep((objPtr), &encodingType, &ir);			\
    } while (0)

#define EncodingGetInternalRep(objPtr, encoding)				\
    do {								\
	const Tcl_ObjInternalRep *irPtr;					\
	irPtr = TclFetchInternalRep ((objPtr), &encodingType);		\
	(encoding) = irPtr ? (Tcl_Encoding)irPtr->twoPtrValue.ptr1 : NULL;		\
    } while (0)


/*
 *----------------------------------------------------------------------
 *
280
281
282
283
284
285
286
287
288
289
290
291
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
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Encoding *encodingPtr)
{
    Tcl_Encoding encoding;
    const char *name = TclGetString(objPtr);

    EncodingGetIntRep(objPtr, encoding);
    if (encoding == NULL) {
	encoding = Tcl_GetEncoding(interp, name);
	if (encoding == NULL) {
	    return TCL_ERROR;
	}
	EncodingSetIntRep(objPtr, encoding);
    }
    *encodingPtr = Tcl_GetEncoding(NULL, name);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeEncodingIntRep --
 *
 *	The Tcl_FreeInternalRepProc for the "encoding" Tcl_ObjType.
 *
 *----------------------------------------------------------------------
 */

static void
FreeEncodingIntRep(
    Tcl_Obj *objPtr)
{
    Tcl_Encoding encoding;

    EncodingGetIntRep(objPtr, encoding);
    Tcl_FreeEncoding(encoding);
}

/*
 *----------------------------------------------------------------------
 *
 * DupEncodingIntRep --
 *
 *	The Tcl_DupInternalRepProc for the "encoding" Tcl_ObjType.
 *
 *----------------------------------------------------------------------
 */

static void
DupEncodingIntRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dupPtr)
{
    Tcl_Encoding encoding = Tcl_GetEncoding(NULL, TclGetString(srcPtr));
    EncodingSetIntRep(dupPtr, encoding);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetEncodingSearchPath --
 *







|





|








|







|




|






|







|




|







314
315
316
317
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
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Encoding *encodingPtr)
{
    Tcl_Encoding encoding;
    const char *name = TclGetString(objPtr);

    EncodingGetInternalRep(objPtr, encoding);
    if (encoding == NULL) {
	encoding = Tcl_GetEncoding(interp, name);
	if (encoding == NULL) {
	    return TCL_ERROR;
	}
	EncodingSetInternalRep(objPtr, encoding);
    }
    *encodingPtr = Tcl_GetEncoding(NULL, name);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeEncodingInternalRep --
 *
 *	The Tcl_FreeInternalRepProc for the "encoding" Tcl_ObjType.
 *
 *----------------------------------------------------------------------
 */

static void
FreeEncodingInternalRep(
    Tcl_Obj *objPtr)
{
    Tcl_Encoding encoding;

    EncodingGetInternalRep(objPtr, encoding);
    Tcl_FreeEncoding(encoding);
}

/*
 *----------------------------------------------------------------------
 *
 * DupEncodingInternalRep --
 *
 *	The Tcl_DupInternalRepProc for the "encoding" Tcl_ObjType.
 *
 *----------------------------------------------------------------------
 */

static void
DupEncodingInternalRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dupPtr)
{
    Tcl_Encoding encoding = Tcl_GetEncoding(NULL, TclGetString(srcPtr));
    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
 *----------------------------------------------------------------------
 */

int
Tcl_SetEncodingSearchPath(
    Tcl_Obj *searchPath)
{
    int dummy;

    if (TCL_ERROR == Tcl_ListObjLength(NULL, searchPath, &dummy)) {
	return TCL_ERROR;
    }
    TclSetProcessGlobalValue(&encodingSearchPath, searchPath, NULL);
    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







|

|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







400
401
402
403
404
405
406
407
408
409
410
411
412
413
414














































415
416
417
418
419
420
421
 *----------------------------------------------------------------------
 */

int
Tcl_SetEncodingSearchPath(
    Tcl_Obj *searchPath)
{
    Tcl_Size dummy;

    if (TCL_ERROR == TclListObjLength(NULL, searchPath, &dummy)) {
	return TCL_ERROR;
    }
    TclSetProcessGlobalValue(&encodingSearchPath, searchPath, NULL);
    return TCL_OK;
}















































/*
 *---------------------------------------------------------------------------
 *
 * 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
 *
 *---------------------------------------------------------------------------
 */

static void
FillEncodingFileMap(void)
{
    int i, numDirs = 0;
    Tcl_Obj *map, *searchPath;

    searchPath = Tcl_GetEncodingSearchPath();
    Tcl_IncrRefCount(searchPath);
    Tcl_ListObjLength(NULL, searchPath, &numDirs);
    map = Tcl_NewDictObj();
    Tcl_IncrRefCount(map);

    for (i = numDirs-1; i >= 0; 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_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);
	for (j=0; j<numFiles; j++) {
	    Tcl_Obj *encodingName, *fileObj;

	    fileObj = TclPathPart(NULL, filev[j], TCL_PATH_TAIL);
	    encodingName = TclPathPart(NULL, fileObj, TCL_PATH_ROOT);
	    Tcl_DictObjPut(NULL, map, encodingName, directory);
	    Tcl_DecrRefCount(fileObj);
	    Tcl_DecrRefCount(encodingName);
	}
	Tcl_DecrRefCount(matchFileList);
	Tcl_DecrRefCount(directory);
    }
    Tcl_DecrRefCount(searchPath);
    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
    Tcl_DecrRefCount(map);







|




|



|





|













|

|


|
|

|







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
 *
 *---------------------------------------------------------------------------
 */

static void
FillEncodingFileMap(void)
{
    Tcl_Size i, numDirs = 0;
    Tcl_Obj *map, *searchPath;

    searchPath = Tcl_GetEncodingSearchPath();
    Tcl_IncrRefCount(searchPath);
    TclListObjLength(NULL, searchPath, &numDirs);
    map = Tcl_NewDictObj();
    Tcl_IncrRefCount(map);

    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.
	 */

	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);

	TclListObjGetElements(NULL, matchFileList, &numFiles, &filev);
	for (j=0; j<numFiles; j++) {
	    Tcl_Obj *encoding, *fileObj;

	    fileObj = TclPathPart(NULL, filev[j], TCL_PATH_TAIL);
	    encoding = TclPathPart(NULL, fileObj, TCL_PATH_ROOT);
	    Tcl_DictObjPut(NULL, map, encoding, directory);
	    Tcl_DecrRefCount(fileObj);
	    Tcl_DecrRefCount(encoding);
	}
	Tcl_DecrRefCount(matchFileList);
	Tcl_DecrRefCount(directory);
    }
    Tcl_DecrRefCount(searchPath);
    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
    Tcl_DecrRefCount(map);
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
 *
 * Side effects:
 *	Depends on the memory, object, and IO subsystems.
 *
 *---------------------------------------------------------------------------
 */












void
TclInitEncodingSubsystem(void)
{
    Tcl_EncodingType type;
    TableEncodingData *dataPtr;
    unsigned size;
    unsigned short i;
    union {
        char c;
        short s;
    } isLe;


    if (encodingsInitialized) {
	return;
    }


    isLe.s = 1;


    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.freeProc	= NULL;
    type.nullSize	= 1;


    type.clientData	= NULL;

    Tcl_CreateEncoding(&type);

    type.toUtfProc	= Utf16ToUtfProc;
    type.fromUtfProc    = UtfToUcs2Proc;
    type.freeProc	= NULL;
    type.nullSize	= 2;
    type.encodingName   = "ucs-2le";
    type.clientData	= INT2PTR(1);
    Tcl_CreateEncoding(&type);
    type.encodingName   = "ucs-2be";
    type.clientData	= INT2PTR(0);
    Tcl_CreateEncoding(&type);
    type.encodingName   = "ucs-2";
    type.clientData	= INT2PTR(isLe.c);














    Tcl_CreateEncoding(&type);

    type.toUtfProc	= Utf16ToUtfProc;
    type.fromUtfProc    = UtfToUtf16Proc;
    type.freeProc	= NULL;
    type.nullSize	= 2;
    type.encodingName   = "utf-16le";
    type.clientData	= INT2PTR(1);
    Tcl_CreateEncoding(&type);
    type.encodingName   = "utf-16be";
    type.clientData	= INT2PTR(0);
    Tcl_CreateEncoding(&type);
    type.encodingName   = "utf-16";
    type.clientData	= INT2PTR(isLe.c);
    Tcl_CreateEncoding(&type);

#ifndef TCL_NO_DEPRECATED
    type.encodingName   = "unicode";
    Tcl_CreateEncoding(&type);
#endif








>
>
>
>
>
>
>
>
>
>
>








|
|

>





>

>
>



















|
|


>
>

>







|


|


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|


|


|







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
 *
 * 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.
 */
#define TCL_ENCODING_LE	0x100   /* Used to distinguish LE/BE variants */
#define ENCODING_UTF	0x200	/* For UTF-8 encoding, allow 4-byte output sequences */
#define 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;
    } 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	= 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.freeProc	= NULL;
    type.nullSize	= 2;
    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-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   = "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(TCL_ENCODING_LE);
    Tcl_CreateEncoding(&type);
    type.encodingName   = "utf-16be";
    type.clientData	= NULL;
    Tcl_CreateEncoding(&type);
    type.encodingName   = "utf-16";
    type.clientData	= INT2PTR(leFlags);
    Tcl_CreateEncoding(&type);

#ifndef TCL_NO_DEPRECATED
    type.encodingName   = "unicode";
    Tcl_CreateEncoding(&type);
#endif

659
660
661
662
663
664
665


666
667
668
669
670
671
672
    Tcl_MutexLock(&encodingMutex);
    encodingsInitialized = 0;
    FreeEncoding(systemEncoding);
    systemEncoding = NULL;
    defaultEncoding = NULL;
    FreeEncoding(tclIdentityEncoding);
    tclIdentityEncoding = 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







>
>







679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
    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
}

/*
 *-------------------------------------------------------------------------
 *
 * Tcl_GetEncodingName --
 *
 *	Given an encoding, return the name that was used to constuct the
 *	encoding.
 *
 * Results:
 *	The name of the encoding.
 *
 * Side effects:
 *	None.







|







822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
}

/*
 *-------------------------------------------------------------------------
 *
 * Tcl_GetEncodingName --
 *
 *	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

    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_MutexUnlock(&encodingMutex);

    FillEncodingFileMap();
    map = TclGetProcessGlobalValue(&encodingFileMap);

    /*







|







887
888
889
890
891
892
893
894
895
896
897
898
899
900
901

    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, 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
	    hPtr = Tcl_NextHashEntry(&search)) {
	Tcl_ListObjAppendElement(NULL, result,
		(Tcl_Obj *) Tcl_GetHashKey(&table, hPtr));
    }
    Tcl_SetObjResult(interp, result);
    Tcl_DeleteHashTable(&table);
}




























/*
 *------------------------------------------------------------------------
 *
 * Tcl_SetSystemEncoding --
 *
 *	Sets the default encoding that should be used whenever the user passes







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    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
    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;


    } else {
	encodingPtr->lengthProc = (LengthProc *) unilen;
    }
    encodingPtr->refCount	= 1;
    encodingPtr->hPtr		= NULL;

  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.
	 */

	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);

    Tcl_MutexUnlock(&encodingMutex);
  }
    return (Tcl_Encoding) encodingPtr;
}

/*
 *-------------------------------------------------------------------------
 *
 * Tcl_ExternalToUtfDString --







|
|
>
>

|




|
|
|
|

|
|
|
|
|
|
|

|
|
|

|
|
|
|

|
|







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
    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 == 2) {
	encodingPtr->lengthProc = (LengthProc *) unilen;
    } else if (typePtr->nullSize == 4) {
	encodingPtr->lengthProc = (LengthProc *) unilen4;
    } else {
	encodingPtr->lengthProc = (LengthProc *) strlen;
    }
    encodingPtr->refCount	= 1;
    encodingPtr->hPtr		= NULL;

    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.
	     */

	    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);

	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
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */


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
				 * encoding-specific string length. */
    Tcl_DString *dstPtr)	/* Uninitialized or free DString in which the
				 * converted string is stored. */
{



























































    char *dst;
    Tcl_EncodingState state;
    const Encoding *encodingPtr;
    int flags, result, soFar, srcRead, dstWrote, dstChars;
    size_t dstLen;



    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 = encodingPtr->lengthProc(src);
    }


    flags = TCL_ENCODING_START | TCL_ENCODING_END;




    while (1) {











	result = encodingPtr->toUtfProc(encodingPtr->clientData, src, srcLen,
		flags, &state, dst, dstLen, &srcRead, &dstWrote, &dstChars);

	soFar = dst + dstWrote - Tcl_DStringValue(dstPtr);











	if (result != TCL_CONVERT_NOSPACE) {



	    Tcl_DStringSetLength(dstPtr, soFar);






















	    return Tcl_DStringValue(dstPtr);
	}


	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;
    }







>





|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|
>

>

>






|







>
|
>
>
|
>

>
>
>
>
>
>
>
>
>
>
>
|
|
>
|

>
>
>
>
>
>
>
>
>
>
|
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


>

<
|







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
 *
 * 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. */
    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 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;

    if (src == NULL) {
	srcLen = 0;
    } else if (srcLen == TCL_INDEX_NONE) {
	srcLen = encodingPtr->lengthProc(src);
    }

    flags &= ~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,
		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) &&
		!(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, (void *)NULL);
		}
	    }
	    if (result != TCL_OK) {
		errno = (result == TCL_CONVERT_NOSPACE) ? ENOMEM : EILSEQ;
	    }
	    return result;
	}

	/* Expand space and continue */
	flags &= ~TCL_ENCODING_START;

	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

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. */
    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
				 * 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







|
|








|







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
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. */
    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. */
    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
	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 (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 there are any null characters in the middle of the buffer,
	 * they will converted to the UTF-8 null character (\xC080). To get
	 * the actual \0 at the end of the destination buffer, we need to
	 * append it manually.  First make room for it...
	 */

	dstLen--;



    }




    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';
    }







>
>
>
>
>
>
>















>
>
>


|





>
>
>
|
>
>
>
>

<









<







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
	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 (\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 {

	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);

	*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
 *	pointer to the value stored in the DString.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

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
				 * strlen(). */
    Tcl_DString *dstPtr)	/* Uninitialized or free DString in which the
				 * converted string is stored. */
{


























































    char *dst;
    Tcl_EncodingState state;
    const Encoding *encodingPtr;
    int flags, result, soFar, srcRead, dstWrote, dstChars;

    size_t dstLen;


    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_START | TCL_ENCODING_END;
    while (1) {











	result = encodingPtr->fromUtfProc(encodingPtr->clientData, src,
		srcLen, flags, &state, dst, dstLen, &srcRead, &dstWrote,
		&dstChars);
	soFar = dst + dstWrote - Tcl_DStringValue(dstPtr);












	if (result != TCL_CONVERT_NOSPACE) {


	    if (encodingPtr->nullSize == 2) {


		Tcl_DStringSetLength(dstPtr, soFar + 1);
	    }












	    Tcl_DStringSetLength(dstPtr, soFar);













	    return Tcl_DStringValue(dstPtr);
	}

	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;
    }







|





|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
>
|

>

>













>
>
|

>
>
>
>
>
>
>
>
>
>
>

|
|
|

>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|



<
|
>







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
 *	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. */
    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 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;
    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,
		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) &&
		!(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];

		    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, (void *)NULL);
		}
	    }
	    if (result != TCL_OK) {
		errno = (result == TCL_CONVERT_NOSPACE) ? ENOMEM : EILSEQ;
	    }
	    return result;
	}

	flags &= ~TCL_ENCODING_START;

	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

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(). */
    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
				 * 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







|
|








|







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

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. */
    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. */
    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
	srcLen = 0;
    } else if (srcLen == TCL_INDEX_NONE) {
	srcLen = strlen(src);
    }
    if (statePtr == NULL) {
	flags |= TCL_ENCODING_START | TCL_ENCODING_END;
	statePtr = &state;







    }
    if (srcReadPtr == NULL) {
	srcReadPtr = &srcRead;
    }
    if (dstWrotePtr == NULL) {
	dstWrotePtr = &dstWrote;
    }
    if (dstCharsPtr == NULL) {
	dstCharsPtr = &dstChars;
    }




    dstLen -= encodingPtr->nullSize;
    result = encodingPtr->fromUtfProc(encodingPtr->clientData, src, srcLen,
	    flags, statePtr, dst, dstLen, srcReadPtr, dstWrotePtr,
	    dstCharsPtr);




    if (encodingPtr->nullSize == 2) {
	dst[*dstWrotePtr + 1] = '\0';
    }
    dst[*dstWrotePtr] = '\0';

    return result;
}

/*
 *---------------------------------------------------------------------------
 *







>
>
>
>
>
>
>











>
>
>


|
|
>
>
>
>
|
<
<
<







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
	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);
    /*
     * Buffer is terminated irrespective of result. Not sure this is
     * reasonable but keep for historical/compatibility reasons.
     */
    memset(&dst[*dstWrotePtr], '\0', encodingPtr->nullSize);




    return result;
}

/*
 *---------------------------------------------------------------------------
 *
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409

1410
1411
1412
1413
1414
1415
1416
 * Side effects:
 *	The absolute pathname for the application is computed and stored to be
 *	returned later by [info nameofexecutable].
 *
 *---------------------------------------------------------------------------
 */
#undef Tcl_FindExecutable
void
Tcl_FindExecutable(
    const char *argv0)		/* The value of the application's argv[0]
				 * (native). */
{
    Tcl_InitSubsystems();
    TclpSetInitialEncodings();
    TclpFindExecutable(argv0);

}

/*
 *---------------------------------------------------------------------------
 *
 * OpenEncodingFileChannel --
 *







|




|


>







1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
 * Side effects:
 *	The absolute pathname for the application is computed and stored to be
 *	returned later by [info nameofexecutable].
 *
 *---------------------------------------------------------------------------
 */
#undef Tcl_FindExecutable
const char *
Tcl_FindExecutable(
    const char *argv0)		/* The value of the application's argv[0]
				 * (native). */
{
    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

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 *searchPath = Tcl_DuplicateObj(Tcl_GetEncodingSearchPath());
    Tcl_Obj *map = TclGetProcessGlobalValue(&encodingFileMap);
    Tcl_Obj **dir, *path, *directory = NULL;
    Tcl_Channel chan = NULL;
    int i, numDirs;

    Tcl_ListObjGetElements(NULL, searchPath, &numDirs, &dir);
    Tcl_IncrRefCount(nameObj);
    Tcl_AppendToObj(fileNameObj, ".enc", -1);
    Tcl_IncrRefCount(fileNameObj);
    Tcl_DictObjGet(NULL, map, nameObj, &directory);

    /*
     * Check that any cached directory is still on the encoding search path.
     */








|





|

|

|







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

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, TCL_INDEX_NONE);
    Tcl_Obj *fileNameObj = Tcl_DuplicateObj(nameObj);
    Tcl_Obj *searchPath = Tcl_DuplicateObj(Tcl_GetEncodingSearchPath());
    Tcl_Obj *map = TclGetProcessGlobalValue(&encodingFileMap);
    Tcl_Obj **dir, *path, *directory = NULL;
    Tcl_Channel chan = NULL;
    Tcl_Size i, numDirs;

    TclListObjGetElements(NULL, searchPath, &numDirs, &dir);
    Tcl_IncrRefCount(nameObj);
    Tcl_AppendToObj(fileNameObj, ".enc", TCL_INDEX_NONE);
    Tcl_IncrRefCount(fileNameObj);
    Tcl_DictObjGet(NULL, map, nameObj, &directory);

    /*
     * Check that any cached directory is still on the encoding search path.
     */

1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
	    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
	}
    }

    if ((NULL == chan) && (interp != NULL)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown encoding \"%s\"", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, NULL);
    }
    Tcl_DecrRefCount(fileNameObj);
    Tcl_DecrRefCount(nameObj);
    Tcl_DecrRefCount(searchPath);

    return chan;
}







|







1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
	    TclSetProcessGlobalValue(&encodingFileMap, map, NULL);
	}
    }

    if ((NULL == chan) && (interp != NULL)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"unknown encoding \"%s\"", name));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "ENCODING", name, (void *)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
    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_CloseEx(NULL, chan, 0);

    return encoding;
}

/*







|







1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
    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, (void *)NULL);
    }
    Tcl_CloseEx(NULL, chan, 0);

    return encoding;
}

/*
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
      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) {
	return NULL;
    }
    line = Tcl_DStringValue(&lineString);

    fallback = (int) strtol(line, &line, 16);
    symbol = (int) strtol(line, &line, 10);
    numPages = (int) strtol(line, &line, 10);







|







1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
      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) < 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
    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);

	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;







|







2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
    pageMemPtr = (unsigned short *) (dataPtr->toUnicode + 256);

    TclNewObj(objPtr);
    Tcl_IncrRefCount(objPtr);
    for (i = 0; i < numPages; i++) {
	int ch;
	const char *p;
	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
    Tcl_EncodingType type;

    init[0] = '\0';
    final[0] = '\0';
    Tcl_DStringInit(&escapeData);

    while (1) {
	int argc;
	const char **argv;
	char *line;
	Tcl_DString lineString;

	Tcl_DStringInit(&lineString);
	if (Tcl_Gets(chan, &lineString) == TCL_IO_FAILURE) {
	    break;
	}
	line = Tcl_DStringValue(&lineString);
	if (Tcl_SplitList(NULL, line, &argc, &argv) != TCL_OK) {
	    Tcl_DStringFree(&lineString);
	    continue;
	}







|





|







2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
    Tcl_EncodingType type;

    init[0] = '\0';
    final[0] = '\0';
    Tcl_DStringInit(&escapeData);

    while (1) {
	Tcl_Size argc;
	const char **argv;
	char *line;
	Tcl_DString lineString;

	Tcl_DStringInit(&lineString);
	if (Tcl_Gets(chan, &lineString) < 0) {
	    break;
	}
	line = Tcl_DStringValue(&lineString);
	if (Tcl_SplitList(NULL, line, &argc, &argv) != TCL_OK) {
	    Tcl_DStringFree(&lineString);
	    continue;
	}
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
		   Tcl_FreeEncoding((Tcl_Encoding) e);
		   e = NULL;
		}
		est.encodingPtr = e;
		Tcl_DStringAppend(&escapeData, (char *) &est, sizeof(est));
	    }
	}
	Tcl_Free((void *)argv);
	Tcl_DStringFree(&lineString);
    }

    size = offsetof(EscapeEncodingData, subTables)
	    + Tcl_DStringLength(&escapeData);
    dataPtr = (EscapeEncodingData *)Tcl_Alloc(size);
    dataPtr->initLen = strlen(init);







|







2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
		   Tcl_FreeEncoding((Tcl_Encoding) e);
		   e = NULL;
		}
		est.encodingPtr = e;
		Tcl_DStringAppend(&escapeData, (char *) &est, sizeof(est));
	    }
	}
	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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
BinaryProc(
    TCL_UNUSED(ClientData),
    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







|







2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
BinaryProc(
    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
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
    memcpy(dst, src, srcLen);
    return result;
}

/*
 *-------------------------------------------------------------------------
 *
 * UtfIntToUtfExtProc --
 *
 *	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.
 *
 * 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.
 *
 * Results:
 *	Returns TCL_OK if conversion was successful.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfExtToUtfIntProc(
    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, 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;

    if (flags & TCL_ENCODING_START) {
    	*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;
    dstEnd = dst + dstLen - TCL_UTF_MAX;

    for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {























































































































	if ((src > srcClose) && (!TclUCS4Complete(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)) {
	    /*

	     * Copy 7bit characters, but skip null-bytes when we are in input
	     * mode, so that they get converted to 0xC080.
	     */



	    *dst++ = *src++;
	} 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);



	} else {
	    src += TclUtfToUCS4(src, chPtr);
	    if ((*chPtr | 0x7FF) == 0xDFFF) {
		/* A surrogate character is detected, handle especially */
		int low = *chPtr;
		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);
			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;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|
|
|












|


|
|
<
<
<
<












|


<
<
<




|
|
<
<
|












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|












|
<
>
|
|
<
>
|
>
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
|
>
|
>
>
>

<
<
<
|
<
<
|
|
|
<
<
<
<
<
<
<







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
    memcpy(dst, src, srcLen);
    return result;
}

/*
 *-------------------------------------------------------------------------
 *


































































































 * UtfToUtfProc --
 *
 *	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
UtfToUtfProc(
    void *clientData,		/* additional flags */
    const char *src,		/* Source string in UTF-8. */
    int srcLen,			/* Source string length in bytes. */
    int flags,			/* TCL_ENCODING_* 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;
    const char *dstStart, *dstEnd;
    int result, numChars, charLimit = INT_MAX;
    int ch;
    int profile;



    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);
    dstEnd = dst + dstLen - ((flags & ENCODING_UTF) ? TCL_UTF_MAX : 6);

    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))) {
	    /*
	     * 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 */
	    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.
	     * Always check before using Tcl_UtfToUniChar. Not doing so can cause
	     * it to run beyond the end of the buffer! If we happen on such an
	     * incomplete char its bytes are made to represent themselves unless
	     * the user has explicitly asked to be told.
	     */

	    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 {
	    size_t len = TclUtfToUniChar(src, &ch);
	    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 > 0x3FF)) {
		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 & 0x0CFF) | 0xDC00;
		}
		*dst++ = (char)(((ch >> 12) | 0xE0) & 0xEF);
		*dst++ = (char)(((ch >> 6) | 0x80) & 0xBF);
		*dst++ = (char)((ch | 0x80) & 0xBF);
		continue;
	    } else if (SURROGATE(ch)) {
		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;
		}
	    }
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
    }

    *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) && (!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;
	}
	len = TclUtfToUniChar(src, &ch);

	if (SURROGATE(ch)) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_UNKNOWN;

		break;
	    }
	    if (PROFILE_REPLACE(flags)) {
		ch = UNICODE_REPLACE_CHAR;





	    }








	}

	src += len;
	if (flags & TCL_ENCODING_LE) {
	    *dst++ = (ch & 0xFF);
	    *dst++ = ((ch >> 8) & 0xFF);
	    *dst++ = ((ch >> 16) & 0xFF);
	    *dst++ = ((ch >> 24) & 0xFF);
	} else {



	    *dst++ = ((ch >> 24) & 0xFF);


	    *dst++ = ((ch >> 16) & 0xFF);
	    *dst++ = ((ch >> 8) & 0xFF);
	    *dst++ = (ch & 0xFF);







	}
    }

    *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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Utf16ToUtfProc(
    ClientData clientData,	/* != NULL means LE, == NUL means BE */
    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







|







2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Utf16ToUtfProc(
    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
    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;


    if (flags & TCL_ENCODING_CHAR_LIMIT) {
	charLimit = *dstCharsPtr;
    }
    result = TCL_OK;


    /* check alignment with utf-16 (2 == sizeof(UTF-16)) */


    if ((srcLen % 2) != 0) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen--;
    }


    /* If last code point is a high surrogate, we cannot handle that yet */




    if ((srcLen >= 2) && ((src[srcLen - (clientData?1:2)] & 0xFC) == 0xD8)) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen-= 2;
    }

    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 (clientData) {
	    ch = (src[1] & 0xFF) << 8 | (src[0] & 0xFF);
	} else {
	    ch = (src[0] & 0xFF) << 8 | (src[1] & 0xFF);
	}


























	/*
	 * 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);







	} else {




	    dst += Tcl_UniCharToUtf(ch, dst);
	}

	src += sizeof(unsigned short);

































    }

    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}







|

>





>
|
>
>




>
>
|
>
>
>
>
|










|





>
|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|
>

>
>
>
>
>
>
>
|
>
>
>
>


>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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 = 0;

    flags |= PTR2INT(clientData);
    if (flags & TCL_ENCODING_CHAR_LIMIT) {
	charLimit = *dstCharsPtr;
    }
    result = TCL_OK;

    /*
     * Check alignment with utf-16 (2 == sizeof(UTF-16))
     */

    if ((srcLen % 2) != 0) {
	result = TCL_CONVERT_MULTIBYTE;
	srcLen--;
    }

    /*
     * 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;
    }

    srcStart = src;
    srcEnd = src + srcLen;

    dstStart = dst;
    dstEnd = dst + dstLen - TCL_UTF_MAX;

    for (numChars = 0; src < srcEnd && numChars <= charLimit; src += 2, numChars++) {
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}

	unsigned short prev = ch;
	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) && !LOW_SURROGATE(ch)) {
	    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 */
		numChars--;
		break;
	    } else if (PROFILE_REPLACE(flags)) {
		/*
		 * Previous loop wrote a single byte to mark the high surrogate.
		 * Replace it with the replacement character. Further, restart
		 * current loop iteration since need to recheck destination space
		 * and reset processing of current character.
		 */
		ch = UNICODE_REPLACE_CHAR;
		dst--;
		dst += Tcl_UniCharToUtf(ch, dst);
		src -= 2;
		numChars--;
		continue;
	    } else {
	    /* Bug [10c2c17c32]. If Hi surrogate not followed by Lo surrogate, finish 3-byte UTF-8 */
		dst += Tcl_UniCharToUtf(-1, dst);
	    }
	}

	/*
	 * 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 if (HIGH_SURROGATE(prev) || HIGH_SURROGATE(ch)) {
	    dst += Tcl_UniCharToUtf(ch | TCL_COMBINE, dst);
	} else if (LOW_SURROGATE(ch) && !PROFILE_TCL8(flags)) {
	    /* Lo surrogate not preceded by Hi surrogate and not tcl8 profile */
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_SYNTAX;
		break;
	    } else {
		/* PROFILE_REPLACE */
		dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
	    }
	} else {
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
    }

    if (HIGH_SURROGATE(ch)) {
	if (PROFILE_STRICT(flags)) {
	    result = TCL_CONVERT_SYNTAX;
	    src -= 2;
	    dst--;
	    numChars--;
	} else if (PROFILE_REPLACE(flags)) {
	    dst--;
	    dst += Tcl_UniCharToUtf(UNICODE_REPLACE_CHAR, dst);
	} else {
	    /* Bug [10c2c17c32]. If Hi surrogate, finish 3-byte UTF-8 */
	    dst += Tcl_UniCharToUtf(-1, dst);
	}
    }

    /*
     * If we had a truncated code unit at the end AND this is the last
     * fragment AND profile is not "strict", stick FFFD in its place.
     */
    if ((flags & TCL_ENCODING_END) && (result == TCL_CONVERT_MULTIBYTE)) {
	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++; /* Go past truncated code unit */
	    }
	}
    }

    *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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfToUtf16Proc(
    ClientData clientData,	/* != NULL means LE, == NUL means BE */
    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. */
{
    const char *srcStart, *srcEnd, *srcClose, *dstStart, *dstEnd;
    int result, numChars;
    Tcl_UniChar *chPtr = (Tcl_UniChar *) statePtr;

    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);


    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) {




#if TCL_UTF_MAX > 3
	    if (*chPtr <= 0xFFFF) {
		*dst++ = (*chPtr & 0xFF);
		*dst++ = (*chPtr >> 8);
	    } else {
		*dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF);
		*dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8;
		*dst++ = (*chPtr & 0xFF);
		*dst++ = ((*chPtr & 0x3) >> 8) | 0xDC;
	    }
#else
	    *dst++ = (*chPtr & 0xFF);
	    *dst++ = (*chPtr >> 8);
#endif
	} else {
#if TCL_UTF_MAX > 3
	    if (*chPtr <= 0xFFFF) {
		*dst++ = (*chPtr >> 8);
		*dst++ = (*chPtr & 0xFF);
	    } else {
		*dst++ = ((*chPtr & 0x3) >> 8) | 0xDC;
		*dst++ = (*chPtr & 0xFF);
		*dst++ = (((*chPtr - 0x10000) >> 18) & 0x3) | 0xD8;
		*dst++ = (((*chPtr - 0x10000) >> 10) & 0xFF);


	    }
#else
	    *dst++ = (*chPtr >> 8);
	    *dst++ = (*chPtr & 0xFF);
#endif
	}
    }
    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}







|



|
<
<
<
<


















<
|
<
<
|








|
>
















|
>
>
>
>
|
|
>
>
>
>
|
|
|
|

|
|
|
|

<
<
<
<

<
|
|
|

<
<
|
|
>
>

<
<
<
<







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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfToUtf16Proc(
    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 - 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;
	}
	len = TclUtfToUniChar(src, &ch);
	if (SURROGATE(ch)) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_UNKNOWN;
		break;
	    }
	    if (PROFILE_REPLACE(flags)) {
		ch = UNICODE_REPLACE_CHAR;
	    }
	}
	src += len;
	if (flags & TCL_ENCODING_LE) {
	    if (ch <= 0xFFFF) {
		*dst++ = (ch & 0xFF);
		*dst++ = (ch >> 8);
	    } else {
		*dst++ = (((ch - 0x10000) >> 10) & 0xFF);
		*dst++ = (((ch - 0x10000) >> 18) & 0x3) | 0xD8;
		*dst++ = (ch & 0xFF);
		*dst++ = ((ch >> 8) & 0x3) | 0xDC;
	    }




	} else {

	    if (ch <= 0xFFFF) {
		*dst++ = (ch >> 8);
		*dst++ = (ch & 0xFF);
	    } else {


		*dst++ = (((ch - 0x10000) >> 18) & 0x3) | 0xD8;
		*dst++ = (((ch - 0x10000) >> 10) & 0xFF);
		*dst++ = ((ch >> 8) & 0x3) | 0xDC;
		*dst++ = (ch & 0xFF);
	    }




	}
    }
    *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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfToUcs2Proc(
    ClientData clientData,	/* != NULL means LE, == NUL means BE */
    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







|







3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
UtfToUcs2Proc(
    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
				 * 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;
#if TCL_UTF_MAX <= 3
    int len;
#endif
    Tcl_UniChar ch = 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);

    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;
	}
#else
	src += TclUtfToUniChar(src, &ch);
	if (ch > 0xFFFF) {
	    ch = 0xFFFD;

	}
#endif


	/*
	 * Need to handle this in a way that won't cause misalignment by
	 * casting dst to a Tcl_UniChar. [Bug 1122671]
	 */

	if (clientData) {
	    *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
				 * 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. */







|
<
<
<


>








|
















<
|
|
>
|
>
>
|

<
<
|
|
>

|
>






|












|



















|







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
				 * 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, len;



    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 - 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;
	}

	len = TclUtfToUniChar(src, &ch);
	if (ch > 0xFFFF) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_UNKNOWN;
		break;
	    }
	    ch = UNICODE_REPLACE_CHAR;
	}


	if (PROFILE_STRICT(flags) && SURROGATE(ch)) {
	    result = TCL_CONVERT_SYNTAX;
	    break;
	}

	src += len;

	/*
	 * Need to handle this in a way that won't cause misalignment by
	 * casting dst to a Tcl_UniChar. [Bug 1122671]
	 */

	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(
    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
    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)];

	} else {
	    ch = pageZero[byte];
	}
	if ((ch == 0) && (byte != 0)) {

	    if (flags & TCL_ENCODING_STOPONERROR) {
		result = TCL_CONVERT_SYNTAX;
		break;
	    }
	    if (prefixBytes[byte]) {
		src--;
	    }





	    ch = (Tcl_UniChar) byte;

	}

	/*
	 * Special case for 1-byte utf chars for speed.
	 */

	if (ch && ch < 0x80) {
	    *dst++ = (char) ch;
	} else {
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
	src++;
    }


    *srcReadPtr = src - srcStart;
    *dstWrotePtr = dst - dstStart;
    *dstCharsPtr = numChars;
    return result;
}

/*







<
|
>
|
>
|
|
>
>
>
>
>
>
>
>
|
>
|
>




>
|






>
>
>
>
>
|
>



|


|







>







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
    for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	byte = *((unsigned char *) src);
	if (prefixBytes[byte]) {

	    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 (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;
		TclUtfToUniChar(chbuf, &ch);
	    }
	}

	/*
	 * Special case for 1-byte Utf chars for speed.
	 */

	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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
TableFromUtfProc(
    ClientData 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. */







|







3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
TableFromUtfProc(
    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
	     */

	    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]
	 */

	if (ch & 0xFFFF0000) {
	    word = 0;
	} else
#else
	if (!len) {
	    word = 0;
	} else
#endif
	    word = fromUnicode[(ch >> 8)][ch & 0xFF];


	if ((word == 0) && (ch != 0)) {
	    if (flags & TCL_ENCODING_STOPONERROR) {
		result = TCL_CONVERT_UNKNOWN;
		break;
	    }
	    word = dataPtr->fallback;
	}
	if (prefixBytes[(word >> 8)] != 0) {
	    if (dst + 1 > dstEnd) {
		result = TCL_CONVERT_NOSPACE;
		break;
	    }
	    dst[0] = (char) (word >> 8);







<
<
<
<
<
|


|
<
<
<
<
<

|
>

|



|







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
	     */

	    result = TCL_CONVERT_MULTIBYTE;
	    break;
	}
	len = TclUtfToUniChar(src, &ch);






	/* Unicode chars > +U0FFFF cannot be represented in any table encoding */
	if (ch & 0xFFFF0000) {
	    word = 0;
	} else {





	    word = fromUnicode[(ch >> 8)][ch & 0xFF];
	}

	if ((word == 0) && (ch != 0)) {
	    if (PROFILE_STRICT(flags)) {
		result = TCL_CONVERT_UNKNOWN;
		break;
	    }
	    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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Iso88591ToUtfProc(
    TCL_UNUSED(ClientData),
    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







|







3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Iso88591ToUtfProc(
    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
    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);

	/*
	 * Special case for 1-byte utf chars for speed.
	 */

	if (ch && ch < 0x80) {
	    *dst++ = (char) ch;
	} else {
	    dst += Tcl_UniCharToUtf(ch, dst);
	}
	src++;
    }








|





|







3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
    for (numChars = 0; src < srcEnd && numChars <= charLimit; numChars++) {
	Tcl_UniChar ch = 0;

	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	ch = *((unsigned char *) src);

	/*
	 * Special case for 1-byte utf chars for speed.
	 */

	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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Iso88591FromUtfProc(
    TCL_UNUSED(ClientData),
    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







|







3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
Iso88591FromUtfProc(
    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
	}
	len = TclUtfToUniChar(src, &ch);

	/*
	 * Check for illegal characters.
	 */

	if (ch > 0xFF
#if TCL_UTF_MAX <= 3
		|| ((ch >= 0xD800) && (len < 3))
#endif
		) {
	    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) '?';
	}

	if (dst > dstEnd) {
	    result = TCL_CONVERT_NOSPACE;
	    break;
	}
	*(dst++) = (char) ch;







|
<
<
<
|
<



<
<
<




|







3586
3587
3588
3589
3590
3591
3592
3593



3594

3595
3596
3597



3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
	}
	len = TclUtfToUniChar(src, &ch);

	/*
	 * Check for illegal characters.
	 */

	if (ch > 0xFF) {



	    if (PROFILE_STRICT(flags)) {

		result = TCL_CONVERT_UNKNOWN;
		break;
	    }



	    /*
	     * Plunge on, using '?' as a fallback character.
	     */

	    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
 *	Memory freed.
 *
 *---------------------------------------------------------------------------
 */

static void
TableFreeProc(
    ClientData clientData)	/* TableEncodingData that specifies
				 * encoding. */
{
    TableEncodingData *dataPtr = (TableEncodingData *)clientData;

    /*
     * Make sure we aren't freeing twice on shutdown. [Bug 219314]
     */







|







3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
 *	Memory freed.
 *
 *---------------------------------------------------------------------------
 */

static void
TableFreeProc(
    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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
EscapeToUtfProc(
    ClientData 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







|







3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
EscapeToUtfProc(
    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
	     * 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) {
		    /*

		     * Skip the unknown escape sequence.
		     */

		    src += longest;
		    continue;
		}
		result = TCL_CONVERT_SYNTAX;
	    } else {
		result = TCL_CONVERT_MULTIBYTE;
	    }
	    break;







|
<
>
|
<
|
|







3809
3810
3811
3812
3813
3814
3815
3816

3817
3818

3819
3820
3821
3822
3823
3824
3825
3826
3827
	     * 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 (!PROFILE_STRICT(flags)) {

		    unsigned skip = longest > left ? left : longest;
		    /* Unknown escape sequence */

		    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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
EscapeFromUtfProc(
    ClientData 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







|







3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
EscapeFromUtfProc(
    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
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
		if (word != 0) {
		    break;
		}
	    }

	    if (word == 0) {
		state = oldState;
		if (flags & TCL_ENCODING_STOPONERROR) {
		    result = TCL_CONVERT_UNKNOWN;
		    break;
		}
		encodingPtr = GetTableEncoding(dataPtr, state);
		tableDataPtr = (const TableEncodingData *)encodingPtr->clientData;
		word = tableDataPtr->fallback;
	    }







|







3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
		if (word != 0) {
		    break;
		}
	    }

	    if (word == 0) {
		state = oldState;
		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
 *	Memory is freed.
 *
 *---------------------------------------------------------------------------
 */

static void
EscapeFreeProc(
    ClientData clientData)	/* EscapeEncodingData that specifies
				 * encoding. */
{
    EscapeEncodingData *dataPtr = (EscapeEncodingData *)clientData;
    EscapeSubTable *subTablePtr;
    int i;

    if (dataPtr == NULL) {







|







4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
 *	Memory is freed.
 *
 *---------------------------------------------------------------------------
 */

static void
EscapeFreeProc(
    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

    return encodingPtr;
}

/*
 *---------------------------------------------------------------------------
 *
 * unilen --
 *
 *	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.







|







4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181

    return encodingPtr;
}

/*
 *---------------------------------------------------------------------------
 *
 * 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
    const char *src)
{
    unsigned short *p;

    p = (unsigned short *) src;
    while (*p != 0x0000) {
	p++;













    }
    return (char *) p - src;
}

/*
 *-------------------------------------------------------------------------
 *







>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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
static void
InitializeEncodingSearchPath(
    char **valuePtr,
    size_t *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
    const char *bytes;
    int i, numDirs;
    Tcl_Obj *libPathObj, *encodingObj, *searchPathObj;

    TclNewLiteralStringObj(encodingObj, "encoding");
    TclNewObj(searchPathObj);
    Tcl_IncrRefCount(encodingObj);
    Tcl_IncrRefCount(searchPathObj);
    libPathObj = TclGetLibraryPath();
    Tcl_IncrRefCount(libPathObj);
    Tcl_ListObjLength(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);
    Tcl_DecrRefCount(searchPathObj);
}



















































































































/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|






|

|




















|
>
>
|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
static void
InitializeEncodingSearchPath(
    char **valuePtr,
    size_t *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
    const char *bytes;
    Tcl_Size i, numDirs, numBytes;
    Tcl_Obj *libPathObj, *encodingObj, *searchPathObj;

    TclNewLiteralStringObj(encodingObj, "encoding");
    TclNewObj(searchPathObj);
    Tcl_IncrRefCount(encodingObj);
    Tcl_IncrRefCount(searchPathObj);
    libPathObj = TclGetProcessGlobalValue(&libraryPath);
    Tcl_IncrRefCount(libPathObj);
    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, &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, ",", (void *)NULL);
	}
	Tcl_AppendStringsToObj(
	    errorObj, " or ", encodingProfiles[numProfiles-1].name, (void *)NULL);

	Tcl_SetObjResult(interp, errorObj);
	Tcl_SetErrorCode(
	    interp, "TCL", "ENCODING", "PROFILE", profileName, (void *)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", (void *)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
/*
 * 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.
 *
 * 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 inline Tcl_Obj *	NewNsObj(Tcl_Namespace *namespacePtr);
static inline int	EnsembleUnknownCallback(Tcl_Interp *interp,
			    EnsembleConfig *ensemblePtr, int objc,
			    Tcl_Obj *const objv[], Tcl_Obj **prefixObjPtr);
static int		NsEnsembleImplementationCmdNR(ClientData 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		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,






|
















|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
 * tclEnsemble.c --
 *
 *	Contains support for ensembles (see TIP#112), which provide simple
 *	mechanism for creating composite commands on top of namespaces.
 *
 * 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 inline Tcl_Obj *	NewNsObj(Tcl_Namespace *namespacePtr);
static inline int	EnsembleUnknownCallback(Tcl_Interp *interp,
			    EnsembleConfig *ensemblePtr, int objc,
			    Tcl_Obj *const objv[], Tcl_Obj **prefixObjPtr);
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(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
};
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
 * 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 */

};

#define ECRSetIntRep(objPtr, ecRepPtr)					\
    do {								\
	Tcl_ObjIntRep ir;						\
	ir.twoPtrValue.ptr1 = (ecRepPtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &ensembleCmdType, &ir);		\
    } while (0)

#define ECRGetIntRep(objPtr, ecRepPtr)					\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((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. */







|
|









|
>


|

|


|


|

|
|









|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
};
enum EnsConfigOpts {
    CONF_MAP, CONF_NAMESPACE, CONF_PARAM, CONF_PREFIX, CONF_SUBCMDS,
    CONF_UNKNOWN
};

/*
 * 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 */
    TCL_OBJTYPE_V0
};

#define ECRSetInternalRep(objPtr, ecRepPtr)					\
    do {								\
	Tcl_ObjInternalRep ir;						\
	ir.twoPtrValue.ptr1 = (ecRepPtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreInternalRep((objPtr), &ensembleCmdType, &ir);		\
    } while (0)

#define ECRGetInternalRep(objPtr, ecRepPtr)					\
    do {								\
	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 {
    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. */
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

190
191
192
193
194
195
196
197
 *	implementation prefix is configured.
 *
 *----------------------------------------------------------------------
 */

int
TclNamespaceEnsembleCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Namespace *namespacePtr;
    Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp), *cxtPtr,
	    *foundNsPtr, *altFoundNsPtr, *actualCxtPtr;
    Tcl_Command token;
    Tcl_DictSearch search;
    Tcl_Obj *listObj;
    const char *simpleName;

    int index, done;

    if (nsPtr == NULL || nsPtr->flags & NS_DYING) {
	if (!Tcl_InterpDeleted(interp)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "tried to manipulate ensemble of deleted namespace",
		    -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "DEAD", NULL);
	}
	return TCL_ERROR;
    }

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], ensembleSubcommands,
	    "subcommand", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum EnsSubcmds) 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;







|











>
|

|




|













|


>
|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
 *	implementation prefix is configured.
 *
 *----------------------------------------------------------------------
 */

int
TclNamespaceEnsembleCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Namespace *namespacePtr;
    Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp), *cxtPtr,
	    *foundNsPtr, *altFoundNsPtr, *actualCxtPtr;
    Tcl_Command token;
    Tcl_DictSearch search;
    Tcl_Obj *listObj;
    const char *simpleName;
    enum EnsSubcmds index;
    int done;

    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", (void *)NULL);
	}
	return TCL_ERROR;
    }

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "subcommand ?arg ...?");
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], ensembleSubcommands,
	    "subcommand", 0, &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch (index) {
    case ENS_CREATE: {
	const char *name;
	Tcl_Size len;
	int allocatedMapFlag = 0;
	/*
	 * Defaults
	 */
	Tcl_Obj *subcmdObj = NULL;
	Tcl_Obj *mapObj = NULL;
	int permitPrefix = 1;
	Tcl_Obj *unknownObj = NULL;
215
216
217
218
219
220
221

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
	 * 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) {







>

|





|







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
	 * 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) {
	    enum EnsCreateOpts idx;
	    if (Tcl_GetIndexFromObj(interp, objv[0], ensembleCreateOptions,
		    "option", 0, &idx) != TCL_OK) {
		if (allocatedMapFlag) {
		    Tcl_DecrRefCount(mapObj);
		}
		return TCL_ERROR;
	    }
	    switch (idx) {
	    case CRT_CMD:
		name = TclGetString(objv[1]);
		cxtPtr = nsPtr;
		continue;
	    case CRT_SUBCMDS:
		if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		    if (allocatedMapFlag) {
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
			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) {
			    patchedDict = Tcl_DuplicateObj(objv[1]);
			}
			Tcl_DictObjPut(NULL, patchedDict, subcmdWordsObj,







|















|







287
288
289
290
291
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
			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", (void *)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, "::", (void *)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,
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

338
339
340
341
342
343
344
		}
		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;
		}
		continue;

	    case CRT_UNKNOWN:
		if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    return TCL_ERROR;
		}







|








>







326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
		}
		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;
		}
		continue;
	    }
	    case CRT_UNKNOWN:
		if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    return TCL_ERROR;
		}
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408
409
410
411
412
413
414
	}
	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 */

	    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:







>



|


|







399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
	}
	token = Tcl_FindEnsemble(interp, objv[2], TCL_LEAVE_ERR_MSG);
	if (token == NULL) {
	    return TCL_ERROR;
	}

	if (objc == 4) {
	    enum EnsConfigOpts idx;
	    Tcl_Obj *resultObj = NULL;		/* silence gcc 4 warning */

	    if (Tcl_GetIndexFromObj(interp, objv[3], ensembleConfigOptions,
		    "option", 0, &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch (idx) {
	    case CONF_SUBCMDS:
		Tcl_GetEnsembleSubcommandList(NULL, token, &resultObj);
		if (resultObj != NULL) {
		    Tcl_SetObjResult(interp, resultObj);
		}
		break;
	    case CONF_PARAM:
494
495
496
497
498
499
500

501
502
503
504
505
506
507
508
		    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 */

	    Tcl_GetEnsembleSubcommandList(NULL, token, &subcmdObj);
	    Tcl_GetEnsembleMappingDict(NULL, token, &mapObj);
	    Tcl_GetEnsembleParameterList(NULL, token, &paramObj);







>
|







500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
		    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 {
	    Tcl_Size len;
	    int 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 */

	    Tcl_GetEnsembleSubcommandList(NULL, token, &subcmdObj);
	    Tcl_GetEnsembleMappingDict(NULL, token, &mapObj);
	    Tcl_GetEnsembleParameterList(NULL, token, &paramObj);
517
518
519
520
521
522
523

524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
	     * 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:







>

|






|







524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
	     * 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) {
		enum EnsConfigOpts idx;
		if (Tcl_GetIndexFromObj(interp, objv[0],ensembleConfigOptions,
			"option", 0, &idx) != TCL_OK) {
		freeMapAndError:
		    if (allocatedMapFlag) {
			Tcl_DecrRefCount(mapObj);
		    }
		    return TCL_ERROR;
		}
		switch (idx) {
		case CONF_SUBCMDS:
		    if (TclListObjLength(interp, objv[1], &len) != TCL_OK) {
			goto freeMapAndError;
		    }
		    subcmdObj = (len > 0 ? objv[1] : NULL);
		    continue;
		case CONF_PARAM:
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
			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]);
			    }







<
|











|
>
>
>
>
>
>
>
>












|







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
			goto freeMapAndError;
		    }
		    if (done) {
			mapObj = NULL;
			continue;
		    }
		    do {

			if (TclListObjLength(interp, listObj, &len) != 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", (void *)NULL);
			    Tcl_DictObjDone(&search);
			    if (patchedDict) {
				Tcl_DecrRefCount(patchedDict);
			    }
			    goto freeMapAndError;
			}
			if (TclListObjGetElements(interp, listObj, &len,
				&listv) != TCL_OK) {
			    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, "::", (void *)NULL);
			    }
			    Tcl_AppendObjToObj(newCmd, listv[0]);
			    Tcl_ListObjReplace(NULL, newList, 0, 1, 1,
				    &newCmd);
			    if (patchedDict == NULL) {
				patchedDict = Tcl_DuplicateObj(objv[1]);
			    }
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
		    }
		    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;







|







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
		    }
		    continue;
		}
		case CONF_NAMESPACE:
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "option -namespace is read-only", -1));
		    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "READ_ONLY",
			    (void *)NULL);
		    goto freeMapAndError;
		case CONF_PREFIX:
		    if (Tcl_GetBooleanFromObj(interp, objv[1],
			    &permitPrefix) != TCL_OK) {
			goto freeMapAndError;
		    }
		    continue;
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    Tcl_Obj *oldList;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	return TCL_ERROR;
    }
    if (subcmdList != NULL) {
	int length;

	if (TclListObjLength(interp, subcmdList, &length) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (length < 1) {
	    subcmdList = NULL;
	}







|



|







795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    Tcl_Obj *oldList;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	return TCL_ERROR;
    }
    if (subcmdList != NULL) {
	Tcl_Size length;

	if (TclListObjLength(interp, subcmdList, &length) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (length < 1) {
	    subcmdList = NULL;
	}
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Obj *paramList)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    Tcl_Obj *oldList;
    int length;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
	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;







|




|







866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
    Tcl_Interp *interp,
    Tcl_Command token,
    Tcl_Obj *paramList)
{
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    Tcl_Obj *oldList;
    Tcl_Size length;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	return TCL_ERROR;
    }
    if (paramList == NULL) {
	length = 0;
    } else {
	if (TclListObjLength(interp, paramList, &length) != TCL_OK) {
	    return TCL_ERROR;
932
933
934
935
936
937
938
939
940
941
942

943
944
945
946
947
948
949
950
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    Tcl_Obj *oldDict;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	return TCL_ERROR;
    }
    if (mapDict != NULL) {

	int size, done;
	Tcl_DictSearch search;
	Tcl_Obj *valuePtr;

	if (Tcl_DictObjSize(interp, mapDict, &size) != TCL_OK) {
	    return TCL_ERROR;
	}








|



>
|







947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    Tcl_Obj *oldDict;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	return TCL_ERROR;
    }
    if (mapDict != NULL) {
	Tcl_Size size;
	int done;
	Tcl_DictSearch search;
	Tcl_Obj *valuePtr;

	if (Tcl_DictObjSize(interp, mapDict, &size) != TCL_OK) {
	    return TCL_ERROR;
	}

959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
	    }
	    bytes = TclGetString(cmdObjPtr);
	    if (bytes[0] != ':' || bytes[1] != ':') {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"ensemble target is not a fully-qualified command",
			-1));
		Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE",
			"UNQUALIFIED_TARGET", NULL);
		Tcl_DictObjDone(&search);
		return TCL_ERROR;
	    }
	}

	if (size < 1) {
	    mapDict = NULL;







|







975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
	    }
	    bytes = TclGetString(cmdObjPtr);
	    if (bytes[0] != ':' || bytes[1] != ':') {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"ensemble target is not a fully-qualified command",
			-1));
		Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE",
			"UNQUALIFIED_TARGET", (void *)NULL);
		Tcl_DictObjDone(&search);
		return TCL_ERROR;
	    }
	}

	if (size < 1) {
	    mapDict = NULL;
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    Tcl_Obj *oldList;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", NULL);
	return TCL_ERROR;
    }
    if (unknownList != NULL) {
	int length;

	if (TclListObjLength(interp, unknownList, &length) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (length < 1) {
	    unknownList = NULL;
	}







|



|







1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    Tcl_Obj *oldList;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	return TCL_ERROR;
    }
    if (unknownList != NULL) {
	Tcl_Size length;

	if (TclListObjLength(interp, unknownList, &length) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (length < 1) {
	    unknownList = NULL;
	}
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    int wasCompiled;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	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;
    wasCompiled = ensemblePtr->flags & ENSEMBLE_COMPILE;

    /*







|







1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;
    int wasCompiled;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"command is not an ensemble", -1));
	Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    wasCompiled = ensemblePtr->flags & ENSEMBLE_COMPILE;

    /*
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != 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;







|







1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *subcmdListPtr = ensemblePtr->subcmdList;
    return TCL_OK;
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != 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;







|







1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *paramListPtr = ensemblePtr->parameterList;
    return TCL_OK;
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != 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;







|







1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *mapDictPtr = ensemblePtr->subcommandDict;
    return TCL_OK;
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != 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;







|







1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *unknownListPtr = ensemblePtr->unknownHandler;
    return TCL_OK;
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != 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;







|







1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *flagsPtr = ensemblePtr->flags;
    return TCL_OK;
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != 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;







|







1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
    Command *cmdPtr = (Command *) token;
    EnsembleConfig *ensemblePtr;

    if (cmdPtr->objProc != TclEnsembleImplementationCmd) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "command is not an ensemble", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "NOT_ENSEMBLE", (void *)NULL);
	}
	return TCL_ERROR;
    }

    ensemblePtr = (EnsembleConfig *)cmdPtr->objClientData;
    *namespacePtrPtr = (Tcl_Namespace *) ensemblePtr->nsPtr;
    return TCL_OK;
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
	if (cmdPtr == NULL
		|| cmdPtr->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);
	    }
	    return NULL;
	}
    }

    return (Tcl_Command) cmdPtr;
}







|







1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
	if (cmdPtr == NULL
		|| cmdPtr->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), (void *)NULL);
	    }
	    return NULL;
	}
    }

    return (Tcl_Command) cmdPtr;
}
1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
1533
    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;

    int i, nameCount = 0, ensembleFlags = 0, hiddenLen;

    /*
     * Construct the path for the ensemble namespace and create it.
     */

    Tcl_DStringInit(&buf);
    Tcl_DStringInit(&hiddenBuf);







>
|







1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
    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 ensembleFlags = 0, hiddenLen;

    /*
     * Construct the path for the ensemble namespace and create it.
     */

    Tcl_DStringInit(&buf);
    Tcl_DStringInit(&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
 *	placed in the interpreter's result.
 *
 *----------------------------------------------------------------------
 */

int
TclEnsembleImplementationCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    return Tcl_NRCallObjProc(interp, NsEnsembleImplementationCmdNR,
	    clientData, objc, objv);
}

static int
NsEnsembleImplementationCmdNR(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    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;

    /*
     * Must recheck objc, since numParameters might have changed. Cf. test
     * namespace-53.9.
     */

  restartEnsembleParse:
    subIdx = 1 + ensemblePtr->numParameters;
    if ((size_t)objc < subIdx + 1) {
	/*
	 * We don't have a subcommand argument. Make error message.
	 */

	Tcl_DString buf;	/* Message being built */

	Tcl_DStringInit(&buf);
	if (ensemblePtr->parameterList) {
	    Tcl_DStringAppend(&buf,
		    TclGetString(ensemblePtr->parameterList), -1);
	    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) {
	/*
	 * 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);
	}
	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.
     */

    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
	 * 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);
	if (ensembleCmd) {
	    if (ensembleCmd->epoch == ensemblePtr->epoch &&
		    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.
     */

    hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable,
	    TclGetString(subObj));
    if (hPtr != NULL) {

	/*
	 * Cache for later in the subcommand object.
	 */

	MakeCachedEnsembleCommand(subObj, ensemblePtr, hPtr, NULL);
    } else if (!(ensemblePtr->flags & TCL_ENSEMBLE_PREFIX)) {
	/*
	 * 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
	 * matches.
	 */

	const char *subcmdName; /* Name of the subcommand, or unique prefix of
				 * it (will be an error for a non-unique
				 * prefix). */
	char *fullName = NULL;	/* Full name of the subcommand. */
	size_t stringLength, i;
	size_t 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.

		     */

		    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.
		 */

		break;
	    }
	}
	if (fullName == NULL) {
	    /*
	     * The subcommand is not a prefix of anything, so bail out!
	     */

	    goto unknownOrAmbiguousSubcommand;
	}
	hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, fullName);
	if (hPtr == NULL) {
	    Tcl_Panic("full name %s not found in supposedly synchronized hash",







|










|















|


|





|

|

















|







|





|
|






|
|
<
<



|

















|
|







|





|





|
|
<


|
|
<

|
|











<
|
|
|
>







<
|
|







|







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
 *	placed in the interpreter's result.
 *
 *----------------------------------------------------------------------
 */

int
TclEnsembleImplementationCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    return Tcl_NRCallObjProc(interp, NsEnsembleImplementationCmdNR,
	    clientData, objc, objv);
}

static int
NsEnsembleImplementationCmdNR(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    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;
    Tcl_Size subIdx;

    /*
     * Must recheck objc since numParameters might have changed. See test
     * namespace-53.9.
     */

  restartEnsembleParse:
    subIdx = 1 + ensemblePtr->numParameters;
    if (objc < subIdx + 1) {
	/*
	 * 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);
	    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_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", (void *)NULL);
	}
	return TCL_ERROR;
    }

    /*
     * 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 so if the internal representtion
	 * is an ensembleCmd, just call it.


	 */
	EnsembleCmdRep *ensembleCmd;

	ECRGetInternalRep(subObj, ensembleCmd);
	if (ensembleCmd) {
	    if (ensembleCmd->epoch == ensemblePtr->epoch &&
		    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 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 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.
	 */

	goto unknownOrAmbiguousSubcommand;
    } else {
	/*
	 * If the command isn't yet confirmed with the hash as part of building
	 * the export table, scan the sorted array for matches.

	 */

	const char *subcmdName; /* Name of the subcommand or unique prefix of
				 * it (a non-unique prefix produces an error). */

	char *fullName = NULL;	/* Full name of the subcommand. */
	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) {
		    /*

		     * 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) {
		/*

		 * 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. Bail out!
	     */

	    goto unknownOrAmbiguousSubcommand;
	}
	hPtr = Tcl_FindHashEntry(&ensemblePtr->subcommandTable, fullName);
	if (hPtr == NULL) {
	    Tcl_Panic("full name %s not found in supposedly synchronized hash",
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
    }

    prefixObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
    Tcl_IncrRefCount(prefixObj);
  runResultingSubcommand:

    /*
     * Do the real work of execution of the subcommand by building an array of
     * 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,
     *
     *   ((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
     * help with that.)
     */

    {
	Tcl_Obj *copyPtr;	/* The actual list of words to dispatch to.
				 * Will be freed by the dispatch engine. */
	Tcl_Obj **copyObjv;
	int copyObjc, prefixObjc;

	Tcl_ListObjLength(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
	 * 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;
	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
     * 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...
     */

    Tcl_ResetResult(interp);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "SUBCOMMAND",
	    TclGetString(subObj), 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);
    } else {
	size_t i;

	for (i=0 ; i<ensemblePtr->subcommandTable.numEntries-1 ; i++) {
	    Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[i], -1);
	    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_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.
 *
 * 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_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;

	if (numIns < numRemoved) {
	    iPtr->ensembleRewrite.numRemovedObjs += numRemoved - numIns;
	    iPtr->ensembleRewrite.numInsertedObjs = numInserted;
	} else {
	    iPtr->ensembleRewrite.numInsertedObjs += numInserted - numRemoved;
	}







|
<
|
|
|
|



|
<



|


|

|

















|
|














|






|
|
|
<















|
|
|
|




|













|














|












|
|















|
|











|







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
    }

    prefixObj = (Tcl_Obj *)Tcl_GetHashValue(hPtr);
    Tcl_IncrRefCount(prefixObj);
  runResultingSubcommand:

    /*
     * Execute the subcommand by populating an array of objects, which might

     * 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 don't do that because caching of the command object should help.

     */

    {
	Tcl_Obj *copyPtr;	/* The list of words to dispatch on.
				 * Will be freed by the dispatch engine. */
	Tcl_Obj **copyObjv;
	Tcl_Size copyObjc, 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 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);
	TclListObjGetElements(NULL, copyPtr, &copyObjc, &copyObjv);
	((Interp *)interp)->lookupNsPtr = ensemblePtr->nsPtr;
	return TclNREvalObjv(interp, copyObjc, copyObjv, TCL_EVAL_INVOKE, NULL);
    }

  unknownOrAmbiguousSubcommand:
    /*
     * 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.

     */

    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;
	}
    }

    /*
     * 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), (void *)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);
    } else {
	Tcl_Size i;

	for (i=0 ; i<ensemblePtr->subcommandTable.numEntries-1 ; i++) {
	    Tcl_AppendToObj(errorObj, ensemblePtr->subcommandArrayPtr[i], -1);
	    Tcl_AppendToObj(errorObj, ", ", 2);
	}
	Tcl_AppendPrintfToObj(errorObj, "or %s",
		ensemblePtr->subcommandArrayPtr[i]);
    }
    Tcl_SetObjResult(interp, errorObj);
    return TCL_ERROR;
}

int
TclClearRootEnsemble(
    TCL_UNUSED(void **),
    Tcl_Interp *interp,
    int result)
{
    TclResetRewriteEnsemble(interp, 1);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitRewriteEnsemble --
 *
 *	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,
    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 {
	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
}

/*
 *----------------------------------------------------------------------
 *
 * TclSpellFix --
 *
 *	Record 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[],
    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_Obj *bad,
    Tcl_Obj *fix)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *const *search;
    Tcl_Obj **store;
    size_t idx;
    size_t size;

    if (iPtr->ensembleRewrite.sourceObjs == NULL) {
	iPtr->ensembleRewrite.sourceObjs = objv;
	iPtr->ensembleRewrite.numRemovedObjs = 0;
	iPtr->ensembleRewrite.numInsertedObjs = 0;
    }








|













|















|
|






|
|







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
}

/*
 *----------------------------------------------------------------------
 *
 * TclSpellFix --
 *
 *	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(
    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,
    Tcl_Size objc,
    Tcl_Size badIdx,
    Tcl_Obj *bad,
    Tcl_Obj *fix)
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *const *search;
    Tcl_Obj **store;
    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
	 */

	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.
	 */

	idx = 1;
	while (idx < size) {
	    if (search[idx] == bad) {
		break;
	    }







|
|







2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
	 */

	search = (Tcl_Obj *const *) search[1];
    }

    if (badIdx < iPtr->ensembleRewrite.numInsertedObjs) {
	/*
	 * Misspelled value was inserted. Cannot directly jump to the bad
	 * value.  Must search.
	 */

	idx = 1;
	while (idx < size) {
	    if (search[idx] == bad) {
		break;
	    }
2196
2197
2198
2199
2200
2201
2202












2203
2204
2205
2206
2207
2208
2209
	TclNRAddCallback(interp, FreeER, tmp, store, NULL, NULL);
    }

    store[idx] = fix;
    Tcl_IncrRefCount(fix);
    TclNRAddCallback(interp, TclNRReleaseValues, fix, NULL, NULL, NULL);
}













/*
 *----------------------------------------------------------------------
 *
 * TclFetchEnsembleRoot --
 *
 *	Returns the root of ensemble rewriting, if any.







>
>
>
>
>
>
>
>
>
>
>
>







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
	TclNRAddCallback(interp, FreeER, tmp, store, NULL, NULL);
    }

    store[idx] = fix;
    Tcl_IncrRefCount(fix);
    TclNRAddCallback(interp, TclNRReleaseValues, fix, NULL, NULL, NULL);
}

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.
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
 *----------------------------------------------------------------------
 */

Tcl_Obj *const *
TclFetchEnsembleRoot(
    Tcl_Interp *interp,
    Tcl_Obj *const *objv,
    int objc,
    int *objcPtr)
{

    Interp *iPtr = (Interp *) interp;

    if (iPtr->ensembleRewrite.sourceObjs) {
	*objcPtr = objc + iPtr->ensembleRewrite.numRemovedObjs
		- iPtr->ensembleRewrite.numInsertedObjs;



	return iPtr->ensembleRewrite.sourceObjs;


    }
    *objcPtr = objc;
    return objv;
}

/*
 * ----------------------------------------------------------------------
 *
 * EnsmebleUnknownCallback --
 *
 *	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).
 *
 * 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.
 *
 * Side effects:
 *	Calls the Tcl interpreter, so arbitrary.
 *
 * ----------------------------------------------------------------------
 */

static inline int
EnsembleUnknownCallback(
    Tcl_Interp *interp,
    EnsembleConfig *ensemblePtr,
    int objc,
    Tcl_Obj *const objv[],
    Tcl_Obj **prefixObjPtr)
{


    int paramc, i, result, prefixObjc;
    Tcl_Obj **paramv, *unknownCmd, *ensObj;

    /*
     * 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++) {
	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
     * 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));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_DELETED",
		    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
     * ensemble is believed to be updated so we should 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.
	 */

	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.
	 */

	TclDecrRefCount(*prefixObjPtr);
	return TCL_CONTINUE;
    }

    /*
     * Oh no! An exceptional result. Convert 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));







|
|

>





>
>
>
|
>
>








|

|
|
|
|
|




|
|


|












>
>
|



|






|






|
|
|
<










|






|
|
<
|








<
<
<
|
<












|







|







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
 *----------------------------------------------------------------------
 */

Tcl_Obj *const *
TclFetchEnsembleRoot(
    Tcl_Interp *interp,
    Tcl_Obj *const *objv,
    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 {
	    sourceObjs = iPtr->ensembleRewrite.sourceObjs;
	}
	return sourceObjs;
    }
    *objcPtr = objc;
    return objv;
}

/*
 * ----------------------------------------------------------------------
 *
 * EnsembleUnknownCallback --
 *
 *	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, i.e. *prefixObjPtr is invalid
 *	TCL_ERROR -	Something went wrong. Error message in interpreter.
 *
 * Side effects:
 *	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)
{
    Tcl_Size paramc;
    int result;
    Tcl_Size i, prefixObjc;
    Tcl_Obj **paramv, *unknownCmd, *ensObj;

    /*
     * 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++) {
	Tcl_ListObjAppendElement(NULL, unknownCmd, objv[i]);
    }
    TclListObjGetElements(NULL, unknownCmd, &paramc, &paramv);
    Tcl_IncrRefCount(unknownCmd);

    /*
     * 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.

     */

    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));
	    Tcl_SetErrorCode(interp, "TCL", "ENSEMBLE", "UNKNOWN_DELETED",
		    (void *)NULL);
	}
	result = TCL_ERROR;
    }
    Tcl_Release(ensemblePtr);

    /*
     * 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,

     * 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);




	/* 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;
	}

	/*
	 * Empty result => reparse.
	 */

	TclDecrRefCount(*prefixObjPtr);
	return TCL_CONTINUE;
    }

    /*
     * 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));
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
	    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);
	} 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
 *	ensemble rep, we can skip some of the deallocation process.)
 *
 * Results:
 *	None
 *
 * Side effects:
 *	Alters the internal representation of the first object parameter.

 *
 *----------------------------------------------------------------------
 */

static void
MakeCachedEnsembleCommand(
    Tcl_Obj *objPtr,
    EnsembleConfig *ensemblePtr,
    Tcl_HashEntry *hPtr,
    Tcl_Obj *fix)
{
    EnsembleCmdRep *ensembleCmd;

    ECRGetIntRep(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
	 * our own.
	 */

	ensembleCmd = (EnsembleCmdRep *)Tcl_Alloc(sizeof(EnsembleCmdRep));
	ECRSetIntRep(objPtr, ensembleCmd);
    }

    /*
     * Populate the internal rep.
     */

    ensembleCmd->epoch = ensemblePtr->epoch;







|














|
|
|
<


|


|
>













|







|
<



|







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
	    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",
		    (void *)NULL);
	} else {
	    Tcl_AddErrorInfo(interp,
		    "\n    (ensemble unknown subcommand handler)");
	}
    }
    TclDecrRefCount(unknownCmd);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * MakeCachedEnsembleCommand --
 *
 *	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.

 *
 * Results:
 *	None.
 *
 * Side effects:
 *	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)
{
    EnsembleCmdRep *ensembleCmd;

    ECRGetInternalRep(objPtr, ensembleCmd);
    if (ensembleCmd) {
	TclCleanupCommandMacro(ensembleCmd->token);
	if (ensembleCmd->fix) {
	    Tcl_DecrRefCount(ensembleCmd->fix);
	}
    } else {
	/*
	 * Replace any old internal representation with a new one.

	 */

	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
}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	commands.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is (eventually) deallocated.
 *
 *----------------------------------------------------------------------
 */

static void
ClearTable(
    EnsembleConfig *ensemblePtr)







|
|
|
|
<





|







2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469

2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteEnsembleConfig --
 *
 *	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.

 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is eventually deallocated.
 *
 *----------------------------------------------------------------------
 */

static void
ClearTable(
    EnsembleConfig *ensemblePtr)
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
        Tcl_Free(ensemblePtr->subcommandArrayPtr);
    }
    Tcl_DeleteHashTable(hash);
}

static void
DeleteEnsembleConfig(
    ClientData clientData)
{
    EnsembleConfig *ensemblePtr = (EnsembleConfig *)clientData;
    Namespace *nsPtr = ensemblePtr->nsPtr;

    /*
     * Unlink from the ensemble chain if it has not been marked as having been
     * done already.
     */

    if (ensemblePtr->next != ensemblePtr) {
	EnsembleConfig *ensPtr = (EnsembleConfig *) nsPtr->ensembles;

	if (ensPtr == ensemblePtr) {
	    nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next;
	} else {







|




<
|
<
<







2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506

2507


2508
2509
2510
2511
2512
2513
2514
        Tcl_Free(ensemblePtr->subcommandArrayPtr);
    }
    Tcl_DeleteHashTable(hash);
}

static void
DeleteEnsembleConfig(
    void *clientData)
{
    EnsembleConfig *ensemblePtr = (EnsembleConfig *)clientData;
    Namespace *nsPtr = ensemblePtr->nsPtr;


    /* Unlink from the ensemble chain if it not already marked as unlinked. */



    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
     * 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.
     */

    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
     * 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.)
     */

    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.
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

static void
BuildEnsembleConfig(
    EnsembleConfig *ensemblePtr)
{
    Tcl_HashSearch search;	/* Used for scanning the set of commands in
				 * the namespace that backs up this
				 * ensemble. */
    size_t 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;

        /*
         * There is a list of exactly what subcommands go in the table.
         * Must 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.
             */

            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]);







|

















|
<
|
|










|
|
|
|
|







|








|
|
<
|










|





|


|


|



|







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
     * Mark the namespace as dead so code that uses Tcl_Preserve() can tell
     * whether disaster happened anyway.
     */

    ensemblePtr->flags |= ENSEMBLE_DEAD;

    /*
     * 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. This is complex because it is

     * 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 --
 *
 *	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
 *	may be an expensive operation.
 *
 *----------------------------------------------------------------------
 */

static void
BuildEnsembleConfig(
    EnsembleConfig *ensemblePtr)
{
    Tcl_HashSearch search;	/* Used for scanning the commands in
				 * the namespace for this ensemble. */

    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) {
        Tcl_Size subc;
        Tcl_Obj **subv, *target, *cmdObj, *cmdPrefixObj;
        const char *name;

        /*
         * There is a list of exactly what subcommands go in the table.
         * Determine the target for each.
         */

        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 < 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]);
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
                }
            }
        } 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;
                }

                /*
		 * Lookup target in the dictionary.
		 */

                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).
                 */

                cmdObj = Tcl_NewStringObj(name, -1);
                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.
         */

        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);

            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
	 * 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.
	 *
	 * Suggestion for future enhancement: compute the unique prefixes and
	 * place them in the hash too, which should make for even faster
	 * 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);








|




















|
|
|
|










|
|
|


















<
|
|
|
<
|
|
|

|
|
<







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
                }
            }
        } else {
            /*
	     * Usual case where we can freely act on the list and dict.
	     */

            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;
                    }
                }

                /*
                 * 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);
            }
        }
    } else if (mapDict) {
        /*
         * 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_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);
        }
    } else {
	/*

	 * 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

	 * 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 for even faster 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);

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
		    if (isNew) {
			Tcl_Obj *cmdObj, *cmdPrefixObj;

			TclNewObj(cmdObj);
			Tcl_AppendStringsToObj(cmdObj,
				ensemblePtr->nsPtr->fullName,
				(ensemblePtr->nsPtr->parentPtr ? "::" : ""),
				nsCmdName, 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
     * 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.
     *
     * 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.
     */

    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:
     *
     * 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.
     */

    i = 0;
    j = hash->numEntries;
    hPtr = Tcl_FirstHashEntry(hash, &search);
    while (hPtr != NULL) {
	ensemblePtr->subcommandArrayPtr[i++] = (char *)Tcl_GetHashKey(hash, hPtr);







|
















|

|
|
|

|
|
|






|
|
|







|
|
|
|
|







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
		    if (isNew) {
			Tcl_Obj *cmdObj, *cmdPrefixObj;

			TclNewObj(cmdObj);
			Tcl_AppendStringsToObj(cmdObj,
				ensemblePtr->nsPtr->fullName,
				(ensemblePtr->nsPtr->parentPtr ? "::" : ""),
				nsCmdName, (void *)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
     * 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, at least
     * not without a lot of preparation, and they're not useful for generating
     * the error message either.
     *
     * 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);

    /*
     * 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,  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);
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
}

/*
 *----------------------------------------------------------------------
 *
 * NsEnsembleStringOrder --
 *
 *	Helper function to compare two pointers to two strings for use with
 *	qsort().
 *
 * Results:
 *	-1 if the first string is smaller, 1 if the second string is smaller,
 *	and 0 if they are equal.
 *
 * Side effects:
 *	None.







|
<







2793
2794
2795
2796
2797
2798
2799
2800

2801
2802
2803
2804
2805
2806
2807
}

/*
 *----------------------------------------------------------------------
 *
 * NsEnsembleStringOrder --
 *
 *	Helper to for uset with sort() that compares two 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.
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840

static void
FreeEnsembleCmdRep(
    Tcl_Obj *objPtr)
{
    EnsembleCmdRep *ensembleCmd;

    ECRGetIntRep(objPtr, ensembleCmd);
    TclCleanupCommandMacro(ensembleCmd->token);
    if (ensembleCmd->fix) {
	Tcl_DecrRefCount(ensembleCmd->fix);
    }
    Tcl_Free(ensembleCmd);
}








|







2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852

static void
FreeEnsembleCmdRep(
    Tcl_Obj *objPtr)
{
    EnsembleCmdRep *ensembleCmd;

    ECRGetInternalRep(objPtr, ensembleCmd);
    TclCleanupCommandMacro(ensembleCmd->token);
    if (ensembleCmd->fix) {
	Tcl_DecrRefCount(ensembleCmd->fix);
    }
    Tcl_Free(ensembleCmd);
}

2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
DupEnsembleCmdRep(
    Tcl_Obj *objPtr,
    Tcl_Obj *copyPtr)
{
    EnsembleCmdRep *ensembleCmd;
    EnsembleCmdRep *ensembleCopy = (EnsembleCmdRep *)Tcl_Alloc(sizeof(EnsembleCmdRep));

    ECRGetIntRep(objPtr, ensembleCmd);
    ECRSetIntRep(copyPtr, ensembleCopy);

    ensembleCopy->epoch = ensembleCmd->epoch;
    ensembleCopy->token = ensembleCmd->token;
    ensembleCopy->token->refCount++;
    ensembleCopy->fix = ensembleCmd->fix;
    if (ensembleCopy->fix) {
	Tcl_IncrRefCount(ensembleCopy->fix);







|
|







2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
DupEnsembleCmdRep(
    Tcl_Obj *objPtr,
    Tcl_Obj *copyPtr)
{
    EnsembleCmdRep *ensembleCmd;
    EnsembleCmdRep *ensembleCopy = (EnsembleCmdRep *)Tcl_Alloc(sizeof(EnsembleCmdRep));

    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
 */

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
				 * 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 ourResult = TCL_ERROR;
    size_t numBytes;
    const char *word;

    TclNewObj(replaced);
    Tcl_IncrRefCount(replaced);
    if (parsePtr->numWords < depth + 1) {
	goto failed;
    }
    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	/*
	 * Too hard.
	 */

	goto failed;
    }

    /*
     * This is where we return to if we are parsing multiple nested compiled
     * ensembles. [info object] is such a beast.
     */








|









|

|




|
|






|







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
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 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 result, flags = 0, depth = 1, invokeAnyway = 0;
    int ourResult = TCL_ERROR;
    Tcl_Size i, len, numBytes;
    const char *word;

    TclNewObj(replaced);
    Tcl_IncrRefCount(replaced);
    if (parsePtr->numWords <= depth) {
	goto tryCompileToInv;
    }
    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	/*
	 * Too hard.
	 */

	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
    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;
    }

    /*
     * 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;
    }

    /*
     * 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;
	const char *str;
	Tcl_Obj *matchObj = NULL;

	if (Tcl_ListObjGetElements(NULL, listObj, &len, &elems) != TCL_OK) {
	    goto failed;
	}
	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;
		}
		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;
		}
		matchObj = elems[i];
	    }
	}
	if (matchObj == NULL) {
	    goto failed;
	}
	result = Tcl_DictObjGet(NULL, mapObj, matchObj, &targetCmdObj);
	if (result != TCL_OK || targetCmdObj == NULL) {
	    goto failed;
	}
	replacement = matchObj;
    } else {
	Tcl_DictSearch s;
	int done, matched;
	Tcl_Obj *tmpObj;








|













|

















|



|
|










|

















|





|



|







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
    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 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 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) {
	Tcl_Size sclen;
	const char *str;
	Tcl_Obj *matchObj = NULL;

	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 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 tryCompileToInv;
		}
		matchObj = elems[i];
	    }
	}
	if (matchObj == NULL) {
	    goto tryCompileToInv;
	}
	result = Tcl_DictObjGet(NULL, mapObj, matchObj, &targetCmdObj);
	if (result != TCL_OK || targetCmdObj == NULL) {
	    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

	/*
	 * 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;
	}

	/*
	 * Iterate over the keys in the dictionary, checking to see if we're a
	 * prefix.
	 */








|







3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081

	/*
	 * 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 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
	/*
	 * If we have anything other than a single match, we've failed the
	 * unique prefix check.
	 */

	if (matched != 1) {
	    invokeAnyway = 1;
	    goto failed;
	}
    }

    /*
     * 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;
    } 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.
	 */








|














|
|







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
	/*
	 * If we have anything other than a single match, we've failed the
	 * unique prefix check.
	 */

	if (matched != 1) {
	    invokeAnyway = 1;
	    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 (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.
	 */

3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
    /*
     * 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
		|| 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]
	     */







|







3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
    /*
     * 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 ((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
	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;
    }

    /*
     * 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:
    if (depth < 250) {
	if (depth > 1) {
	    if (!invokeAnyway) {
		cmdPtr = oldCmdPtr;
		depth--;
	    }
	}







|

















|







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
	goto cleanup;
    }

    /*
     * Throw out any line information generated by the failed compile attempt.
     */

    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.
     */

  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
    return ourResult;
}

int
TclAttemptCompileProc(
    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    int depth,
    Command *cmdPtr,
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;
    int result, i;

    Tcl_Token *saveTokenPtr = parsePtr->tokenPtr;
    int savedStackDepth = envPtr->currStackDepth;
    unsigned savedCodeNext = envPtr->codeNext - envPtr->codeStart;
    int savedAuxDataArrayNext = envPtr->auxDataArrayNext;
    int savedExceptArrayNext = envPtr->exceptArrayNext;
#ifdef TCL_COMPILE_DEBUG
    int savedExceptDepth = envPtr->exceptDepth;
#endif

    if (cmdPtr->compileProc == NULL) {
	return TCL_ERROR;
    }

    /*







|




|
>

|
|
|
|

|







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
    return ourResult;
}

int
TclAttemptCompileProc(
    Tcl_Interp *interp,
    Tcl_Parse *parsePtr,
    Tcl_Size depth,
    Command *cmdPtr,
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;
    int result;
    Tcl_Size i;
    Tcl_Token *saveTokenPtr = parsePtr->tokenPtr;
    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
    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
#endif

    if (result != TCL_OK) {
	ExceptionAux *auxPtr = envPtr->exceptAuxArrayPtr;

	for (i = 0; i < savedExceptArrayNext; i++) {
	    while (auxPtr->numBreakTargets > 0
		    && auxPtr->breakTargets[auxPtr->numBreakTargets - 1]
		    >= savedCodeNext) {
		auxPtr->numBreakTargets--;
	    }
	    while (auxPtr->numContinueTargets > 0
		    && auxPtr->continueTargets[auxPtr->numContinueTargets - 1]
		    >= savedCodeNext) {
		auxPtr->numContinueTargets--;
	    }
	    auxPtr++;
	}
	envPtr->exceptArrayNext = savedExceptArrayNext;








|




|







3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
#endif

    if (result != TCL_OK) {
	ExceptionAux *auxPtr = envPtr->exceptAuxArrayPtr;

	for (i = 0; i < savedExceptArrayNext; i++) {
	    while (auxPtr->numBreakTargets > 0
		    && (Tcl_Size) auxPtr->breakTargets[auxPtr->numBreakTargets - 1]
		    >= savedCodeNext) {
		auxPtr->numBreakTargets--;
	    }
	    while (auxPtr->numContinueTargets > 0
		    && (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
    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;

    /*
     * 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);
    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);
	    PushLiteral(envPtr, bytes, length);
	    continue;
	}

	SetLineInformation(i);
	if (tokPtr->type == TCL_TOKEN_SIMPLE_WORD) {







|
|







|


|







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
    Command *cmdPtr,
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    DefineLineInformation;
    Tcl_Token *tokPtr;
    Tcl_Obj *objPtr, **words;
    const char *bytes;
    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...
     */

    TclListObjGetElements(NULL, replacements, &numWords, &words);
    for (i = 0, tokPtr = parsePtr->tokenPtr; i < parsePtr->numWords;
	    i++, tokPtr = TokenAfter(tokPtr)) {
	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) {
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
 */

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
				 * 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
				 * 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.







|



















|







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
 */

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 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 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
}

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
				 * 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.







|







3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
}

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 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
}

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
				 * 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.







|







3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
}

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 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
}

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
				 * 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.







|







3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
}

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 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
}

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
				 * 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.







|







3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
}

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 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
}

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
				 * 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.







|







3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
}

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 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
}

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
				 * 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.







|







3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
}

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 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
}

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
				 * 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.







|







3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
}

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 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
}

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
				 * 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.







|







3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
}

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 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
}

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
				 * 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) {
	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
				 * 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) {
	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
				 * 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) {
	return TCL_ERROR;
    }

    return CompileBasicNArgCommand(interp, parsePtr, cmdPtr, envPtr);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|









|











|









|











|









|













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
}

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 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 ((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 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 ((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 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 ((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
/*
 * 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.
 *
 * 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 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 techar char
#endif






static struct {
    size_t 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
				 * 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,
			    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);

/*
 *----------------------------------------------------------------------








|
|











|
|
|
|






|
|
|
|



>
>
>
>
>

|







|













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
 * 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 © 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(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(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 {
    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. */
    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(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

	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);




	    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.
		 */







|
>
>
>
>







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

	Tcl_MutexLock(&envMutex);
	for (i = 0; tenviron[i] != NULL; i++) {
	    Tcl_Obj *obj1, *obj2;
	    const char *p1;
	    char *p2;

	    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
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;
    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.







|
|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
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;
    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
	 * 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);
	    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);







    /*
     * Copy the native string to heap memory.
     */

    p = (char *)Tcl_Realloc(p, Tcl_DStringLength(&envString) + tNTL);
    memcpy(p, p2, Tcl_DStringLength(&envString) + tNTL);







|
|
|




















|
>
>
>
>
>
>







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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
	 * 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], &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, &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
	 */

	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 --
 *







<
<
<
<
<
<
<
<
<







370
371
372
373
374
375
376









377
378
379
380
381
382
383
	 */

	Tcl_Free(p);
#endif /* HAVE_PUTENV_THAT_COPIES */
    }

    Tcl_MutexUnlock(&envMutex);









}

/*
 *----------------------------------------------------------------------
 *
 * 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
    char *value;

    if (assignment == NULL) {
	return 0;
    }

    /*
     * 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);
    value = (char *)strchr(name, '=');

    if ((value != NULL) && (value != name)) {
	value[0] = '\0';










	TclSetEnv(name, value+1);
    }


    Tcl_DStringFree(&nameString);
    return 0;
}

/*
 *----------------------------------------------------------------------







|



|




>
>
>
>
>
>
>
>
>
>


>







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
    char *value;

    if (assignment == NULL) {
	return 0;
    }

    /*
     * 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, 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
 */

void
TclUnsetEnv(
    const char *name)		/* Name of variable to remove (UTF-8). */
{
    char *oldValue;
    size_t 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) {
	Tcl_MutexUnlock(&envMutex);
	return;
    }

    /*
     * Remember the old value so we can free it if Tcl created the string.
     */







|















|







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
 */

void
TclUnsetEnv(
    const char *name)		/* Name of variable to remove (UTF-8). */
{
    char *oldValue;
    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 == -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
    string[length+1] = '\0';
#else
    string = (char *)Tcl_Alloc(length + 1);
    memcpy(string, name, length);
    string[length] = '\0';
#endif /* _WIN32 */

    utf2tenvirondstr(string, -1, &envString);




    string = (char *)Tcl_Realloc(string, Tcl_DStringLength(&envString) + tNTL);
    memcpy(string, Tcl_DStringValue(&envString),
	    Tcl_DStringLength(&envString) + tNTL);
    Tcl_DStringFree(&envString);

    putenv(string);








|
>
>
>
>







508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
    string[length+1] = '\0';
#else
    string = (char *)Tcl_Alloc(length + 1);
    memcpy(string, name, length);
    string[length] = '\0';
#endif /* _WIN32 */

    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
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;
    const char *result;

    Tcl_MutexLock(&envMutex);
    index = TclpFindVariable(name, &length);
    result = NULL;
    if (index != TCL_INDEX_NONE) {
	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);

    }
    Tcl_MutexUnlock(&envMutex);
    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
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. */
{
    Tcl_Size length, index;
    const char *result;

    Tcl_MutexLock(&envMutex);
    index = TclpFindVariable(name, &length);
    result = NULL;
    if (index != -1) {
	Tcl_DString 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
 *	this happens because the whole interpreter is being deleted).
 *
 *----------------------------------------------------------------------
 */

static char *
EnvTraceProc(
    TCL_UNUSED(ClientData),
    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);

	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;


	value = Tcl_GetVar2(interp, "env", name2, TCL_GLOBAL_ONLY);










	TclSetEnv(name2, value);

    }

    /*
     * If a value is being read, call TclGetEnv to do all of the work.
     */

    if (flags & TCL_TRACE_READS) {







|













>

















>


>
>
>
>
>
>
>
>
>
>

>







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
 *	this happens because the whole interpreter is being deleted).
 *
 *----------------------------------------------------------------------
 */

static char *
EnvTraceProc(
    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

    /*
     * For unset traces, let TclUnsetEnv do all the work.
     */

    if (flags & TCL_TRACE_UNSETS) {
	TclUnsetEnv(name2);

    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *







>







698
699
700
701
702
703
704
705
706
707
708
709
710
711
712

    /*
     * 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
 */

static void
ReplaceString(
    const char *oldStr,		/* Old environment string. */
    char *newStr)		/* New environment string. */
{
    size_t 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.
     */







|







726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
 */

static void
ReplaceString(
    const char *oldStr,		/* Old environment string. */
    char *newStr)		/* New environment string. */
{
    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
     * 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;
	for (i = 0; i < env.cacheSize; i++) {
	    Tcl_Free(env.cache[i]);
	}
#endif
	Tcl_Free(env.cache);
	env.cache = NULL;
	env.cacheSize = 0;







|







805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
     * 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
	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
/*
 * 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.
 *
 * 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 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.
 */








|
|
|






>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * tclEvent.c --
 *
 *	This file implements some general event related interfaces including
 *	background errors, exit handlers, and the "vwait" and "update" command
 *	functions.
 *
 * 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"

/*
 * 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
				 * 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 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. */







>
>
>
>
>
>
>
>
>
>
>
>
>







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
				 * 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
 * in closing of files and pipes.
 */

static int inExit = 0;

static int subsystemsInitialized = 0;



/*
 * 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;







>
>







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
 * 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;
111
112
113
114
115
116
117



118
119
120
121
122
123
124
/*
 * Prototypes for functions referenced only in this file:
 */

static void		BgErrorDeleteProc(void *clientData,
			    Tcl_Interp *interp);
static void		HandleBgErrors(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);

/*







>
>
>







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * 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
     * 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;

	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);
	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);








|
>











|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
     * 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;
	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;

	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);

261
262
263
264
265
266
267
268


269
270


271
272
273
274
275
276
277
		Tcl_IncrRefCount(keyPtr);
		Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr);
		Tcl_DecrRefCount(keyPtr);

		Tcl_WriteChars(errChannel,
			"error in background error handler:\n", -1);
		if (valuePtr) {
		    Tcl_WriteObj(errChannel, valuePtr);


		} else {
		    Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));


		}
		Tcl_WriteChars(errChannel, "\n", 1);
		Tcl_Flush(errChannel);
		Tcl_DecrRefCount(options);
	    }
	}
    }







|
>
>

|
>
>







281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
		Tcl_IncrRefCount(keyPtr);
		Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr);
		Tcl_DecrRefCount(keyPtr);

		Tcl_WriteChars(errChannel,
			"error in background error handler:\n", -1);
		if (valuePtr) {
		    if (Tcl_WriteObj(errChannel, valuePtr) < 0) {
			Tcl_WriteChars(errChannel, ENCODING_ERROR, -1);
		    }
		} else {
		    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);
	    }
	}
    }
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
    TclNewLiteralStringObj(keyPtr, "-level");
    Tcl_IncrRefCount(keyPtr);
    result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &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);
	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);
    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);
	return TCL_ERROR;
    }
    if (Tcl_GetIntFromObj(interp, valuePtr, &code) == TCL_ERROR) {
	return TCL_ERROR;
    }

    if (level != 0) {







|












|







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
    TclNewLiteralStringObj(keyPtr, "-level");
    Tcl_IncrRefCount(keyPtr);
    result = Tcl_DictObjGet(NULL, objv[2], keyPtr, &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", (void *)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);
    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", (void *)NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetIntFromObj(interp, valuePtr, &code) == TCL_ERROR) {
	return TCL_ERROR;
    }

    if (level != 0) {
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
	    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));


		    Tcl_WriteChars(errChannel, "\n", -1);
		} else {
		    Tcl_DiscardInterpState(saved);
		    Tcl_WriteChars(errChannel,
			    "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);


		    Tcl_WriteChars(errChannel, "\n", -1);
		}
		Tcl_DecrRefCount(resultPtr);
		Tcl_Flush(errChannel);
	    } else {
		Tcl_DiscardInterpState(saved);
	    }







|
|
>
>



|
<
|
|
|
>
|
|
>
>







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
	    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);
		    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, "bgerror failed to handle"

			    " 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
/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Background error information is freed: if there were any pending error
 *	reports, they are canceled.







|







595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
/*
 *----------------------------------------------------------------------
 *
 * 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 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.
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
    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.
     *
     * If subsystems are not (yet) initialized, proper Tcl-finalization is
     * impossible, so fallback to system exit, see bug-[f8a33ce3db5d8cc2].
     */

    if (currentAppExitPtr) {








|







963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
    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 dependency.
     *
     * If subsystems are not (yet) initialized, proper Tcl-finalization is
     * impossible, so fallback to system exit, see bug-[f8a33ce3db5d8cc2].
     */

    if (currentAppExitPtr) {

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
 *	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.
 *
 * Side effects:
 *	Varied, see the respective initialization routines.
 *
 *-------------------------------------------------------------------------
 */


void














































































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
	 * this routine from some of the functions below.
	 */

	TclpInitLock();
	if (subsystemsInitialized == 0) {

		/*







|







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|







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
 *	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:
 *	The full Tcl version with build information.
 *
 * Side effects:
 *	Varied, see the respective initialization routines.
 *
 *-------------------------------------------------------------------------
 */

MODULE_SCOPE const TclStubs tclStubs;

#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
}};

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 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
	    TclInitEncodingSubsystem();	/* Process wide encoding init. */
	    TclInitNamespaceSubsystem();/* Register ns obj type (mutexed). */
	    subsystemsInitialized = 1;
	}
	TclpInitUnlock();
    }
    TclInitNotifier();

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Finalize --
 *







>







1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
	    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
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;
    }
    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;
    };
































    done = 0;



















































































































































































    foundEvent = 1;
    while (!done && foundEvent) {

	foundEvent = Tcl_DoOneEvent(TCL_ALL_EVENTS);
	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));

	    break;
	}








    }
    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;

    }

    if (!done) {
	/*
	 * The interpreter's result was already set to the right error message
	 * prior to exiting the loop above.
	 */



	return TCL_ERROR;








    }

    /*
     * Clear out the interpreter's result, since it may have been set by event
     * handlers.
     */




































































    Tcl_ResetResult(interp);




















    return TCL_OK;



































}

static char *
VwaitVarProc(
    void *clientData,		/* Pointer to integer to set to 1. */
    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;




    *donePtr = 1;

    Tcl_UntraceVar2(interp, name1, name2, TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
	    VwaitVarProc, clientData);
    return NULL;
}

/*
 *----------------------------------------------------------------------







|
|
|
|
|
|
<
|
>
|
|
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
|






>


>
>
>
>
>
>
>
>
|
<
<
<
>



|
|
>
|
|
|
>

>
|




>
>
|
|
>
>
>
>
>
>
>
>



|
<

>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|





|

>
>
>
|
>







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
int
Tcl_VwaitObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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;

    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:
	    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", (void *)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", (void *)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", (void *)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", (void *)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", (void *)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 (!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", (void *)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;
	}



    }

    if (!foundEvent) {
	Tcl_ResetResult(interp);
	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", (void *)NULL);
	result = TCL_ERROR;
	goto 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;
    }

    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;
    }

    /*
     * When timeout was specified, report milliseconds left or -1 on timeout.

     */
    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;
	}
    }

  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 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. */
{
    VwaitItem *itemPtr = (VwaitItem *) clientData;

    if (itemPtr->donePtr != NULL) {
	itemPtr->sequence = itemPtr->donePtr[0];
	itemPtr->donePtr[0] += 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
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};

    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) {
	case OPT_IDLETASKS:
	    flags = TCL_WINDOW_EVENTS|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;







<


|








|

|







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
int
Tcl_UpdateObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    int flags = 0;		/* Initialized to avoid compiler warning. */
    static const char *const updateOptions[] = {"idletasks", NULL};
    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 (optionIndex) {
	case OPT_IDLETASKS:
	    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
 *----------------------------------------------------------------------
 */

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 */
    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






    return TCL_ERROR;
#endif /* TCL_THREADS */
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|
|















>
>
>
>
>
>











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
 *----------------------------------------------------------------------
 */

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 */
    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
/*
 * 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 <[email protected]>
 * Copyright (c) 2006-2008 by 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"





|
|
|
|
|
|
|







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 © 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 <[email protected]>
 * 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
 * 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 */
                                /* execution. */
    void *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->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);				\







|
|
|
<
|



















|

|
|







107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
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 */
				/* -----------------------------------------*/
    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. */

    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)->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);				\
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
#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_AT_DEPTH(n)	*(tosPtr-(n))

#define CURR_DEPTH	((ptrdiff_t) (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;							\
    }
#   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;							\
    }
#   define O2S(objPtr) \







|

|

|












|
|
|













|
|
|







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
#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_AT_DEPTH(n)	tosPtr[-(n)]

#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, "%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, "%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) \
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
	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:
 *
 * MODULE_SCOPE int GetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
 *			ClientData *ptrPtr, int *tPtr);
 */

#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \
    ((TclHasIntRep((objPtr), &tclIntType))					\
	?	(*(tPtr) = TCL_NUMBER_INT,				\
		*(ptrPtr) = (void *)				\
		    (&((objPtr)->internalRep.wideValue)), TCL_OK) :	\
    TclHasIntRep((objPtr), &tclDoubleType)				\
	?	(((TclIsNaN((objPtr)->internalRep.doubleValue))		\
		    ?	(*(tPtr) = TCL_NUMBER_NAN)			\
		    :	(*(tPtr) = TCL_NUMBER_DOUBLE)),			\
		*(ptrPtr) = (void *)				\
		    (&((objPtr)->internalRep.doubleValue)), TCL_OK) :	\
    (((objPtr)->bytes != NULL) && ((objPtr)->length == 0))		\
	? TCL_ERROR :			\
    TclGetNumberFromObj((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);







|


|



|

|

|
|


|



|







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
	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
 * Tcl_GetNumberFromObj(). The ANSI C "prototype" is:
 *
 * MODULE_SCOPE int GetNumberFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
 *			void **ptrPtr, int *tPtr);
 */

#define GetNumberFromObj(interp, objPtr, ptrPtr, tPtr) \
    ((TclHasInternalRep((objPtr), &tclIntType))				\
	?	(*(tPtr) = TCL_NUMBER_INT,				\
		*(ptrPtr) = (void *)					\
		    (&((objPtr)->internalRep.wideValue)), TCL_OK) :	\
    TclHasInternalRep((objPtr), &tclDoubleType)				\
	?	(((isnan((objPtr)->internalRep.doubleValue))		\
		    ?	(*(tPtr) = TCL_NUMBER_NAN)			\
		    :	(*(tPtr) = TCL_NUMBER_DOUBLE)),			\
		*(ptrPtr) = (void *)					\
		    (&((objPtr)->internalRep.doubleValue)), TCL_OK) :	\
    (((objPtr)->bytes != NULL) && ((objPtr)->length == 0))		\
	? TCL_ERROR :			\
    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);
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
#define OUT_OF_MEMORY ((Tcl_Obj *) -4)

/*
 * Declarations for local procedures to this file:
 */

#ifdef TCL_COMPILE_STATS
static int		EvalStatsCmd(ClientData clientData,
			    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,
			    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,
			    int move);
static void		IllegalExprOperandType(Tcl_Interp *interp,
			    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? */







|
<
<






|















|
|
|







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
#define OUT_OF_MEMORY ((Tcl_Obj *) -4)

/*
 * Declarations for local procedures to this file:
 */

#ifdef TCL_COMPILE_STATS
static Tcl_ObjCmdProc EvalStatsCmd;


#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, 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, 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,
			    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? */
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
 */

static const Tcl_ObjType exprCodeType = {
    "exprcode",
    FreeExprCodeInternalRep,	/* freeIntRepProc */
    DupExprCodeInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    NULL			/* setFromAnyProc */

};

/*
 * 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

};

/*
 *----------------------------------------------------------------------
 *
 * ReleaseDictIterator --
 *







|
>










|
>







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
 */

static const Tcl_ObjType exprCodeType = {
    "exprcode",
    FreeExprCodeInternalRep,	/* freeIntRepProc */
    DupExprCodeInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    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,
    TCL_OBJTYPE_V0
};

/*
 *----------------------------------------------------------------------
 *
 * ReleaseDictIterator --
 *
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713

static void
ReleaseDictIterator(
    Tcl_Obj *objPtr)
{
    Tcl_DictSearch *searchPtr;
    Tcl_Obj *dictPtr;
    const Tcl_ObjIntRep *irPtr;

    irPtr = TclFetchIntRep(objPtr, &dictIteratorType);
    assert(irPtr != NULL);

    /*
     * First kill the search, and then release the reference to the dictionary
     * that we were holding.
     */








|

|







696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712

static void
ReleaseDictIterator(
    Tcl_Obj *objPtr)
{
    Tcl_DictSearch *searchPtr;
    Tcl_Obj *dictPtr;
    const Tcl_ObjInternalRep *irPtr;

    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
 *----------------------------------------------------------------------
 */

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
				 * [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;







|







788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
 *----------------------------------------------------------------------
 */

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
				 * [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
 *----------------------------------------------------------------------
 */

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. */
    int move)			/* 1 if move words since last marker. */
{
    ExecStack *esPtr = eePtr->execStackPtr, *oldPtr = NULL;
    size_t newBytes;

    int newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr);
    Tcl_Obj **markerPtr = esPtr->markerPtr, **memStart;
    int moveWords = 0;

    if (move) {
	if (!markerPtr) {
	    Tcl_Panic("STACK: Reallocating with no previous alloc");
	}
	if (needed <= 0) {
	    return MEMSTART(markerPtr);







|





>
|

|







970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
 *----------------------------------------------------------------------
 */

static Tcl_Obj **
GrowEvaluationStack(
    ExecEnv *eePtr,		/* Points to the ExecEnv with an evaluation
				 * stack to enlarge. */
    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;
    Tcl_Size newElems, currElems, needed = growth - (esPtr->endPtr - esPtr->tosPtr);
    Tcl_Obj **markerPtr = esPtr->markerPtr, **memStart;
    Tcl_Size moveWords = 0;

    if (move) {
	if (!markerPtr) {
	    Tcl_Panic("STACK: Reallocating with no previous alloc");
	}
	if (needed <= 0) {
	    return MEMSTART(markerPtr);
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
    Tcl_Interp *interp,
    size_t numBytes)
{
    Interp *iPtr = (Interp *) interp;
    size_t numWords;

    if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
	return (void *) Tcl_Alloc(numBytes);
    }
    numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
    return StackAllocWords(interp, numWords);
}

void *
TclStackRealloc(







|







1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
    Tcl_Interp *interp,
    size_t numBytes)
{
    Interp *iPtr = (Interp *) interp;
    size_t numWords;

    if (iPtr == NULL || iPtr->execEnvPtr == NULL) {
	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
	    NULL, NULL);
    Tcl_NRExprObj(interp, objPtr, resultPtr);
    return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
}

static int
CopyCallback(
    ClientData 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) {







|







1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
	    NULL, NULL);
    Tcl_NRExprObj(interp, objPtr, resultPtr);
    return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
}

static int
CopyCallback(
    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
    Tcl_NRAddCallback(interp, ExprObjCallback, state, resultPtr,
	    NULL, NULL);
    return TclNRExecuteByteCode(interp, codePtr);
}

static int
ExprObjCallback(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_InterpState state = (Tcl_InterpState)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
    Tcl_NRAddCallback(interp, ExprObjCallback, state, resultPtr,
	    NULL, NULL);
    return TclNRExecuteByteCode(interp, codePtr);
}

static int
ExprObjCallback(
    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) {
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
				 * 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);

    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);
	    codePtr = NULL;
	}
    }

    if (codePtr == NULL) {
	/*
	 * TIP #280: No invoker (yet) - Expression compilation.
	 */

	size_t 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,







|









|









|







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
				 * to avoid compiler warning. */

    /*
     * Get the expression ByteCode from the object. If it exists, make sure it
     * is valid in the current context.
     */

    ByteCodeGetInternalRep(objPtr, &exprCodeType, 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_StoreInternalRep(objPtr, &exprCodeType, NULL);
	    codePtr = NULL;
	}
    }

    if (codePtr == NULL) {
	/*
	 * TIP #280: No invoker (yet) - Expression compilation.
	 */

	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,
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500

/*
 *----------------------------------------------------------------------
 *
 * DupExprCodeInternalRep --
 *
 *	Part of the Tcl object type implementation for Tcl expression
 *	bytecode. We do not copy the bytecode intrep. 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,
 *	like we do for lists and dicts.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.







|








|







1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500

/*
 *----------------------------------------------------------------------
 *
 * DupExprCodeInternalRep --
 *
 *	Part of the Tcl object type implementation for Tcl expression
 *	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 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
 */

static void
FreeExprCodeInternalRep(
    Tcl_Obj *objPtr)
{
    ByteCode *codePtr;
    ByteCodeGetIntRep(objPtr, &exprCodeType, codePtr);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

/*
 *----------------------------------------------------------------------







|







1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
 */

static void
FreeExprCodeInternalRep(
    Tcl_Obj *objPtr)
{
    ByteCode *codePtr;
    ByteCodeGetInternalRep(objPtr, &exprCodeType, codePtr);
    assert(codePtr != NULL);

    TclReleaseByteCode(codePtr);
}

/*
 *----------------------------------------------------------------------
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582

    /*
     * 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);
    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







|







1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582

    /*
     * 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.
     */

    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
	 * 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
	 *     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







|







1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
	 * 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
	 *     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
     * information.
     */

    iPtr->invokeCmdFramePtr = invoker;
    iPtr->invokeWord = word;
    TclSetByteCodeFromAny(interp, objPtr, NULL, NULL);
    iPtr->invokeCmdFramePtr = NULL;
    ByteCodeGetIntRep(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
 *	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.
 *
 *----------------------------------------------------------------------
 */

int
TclIncrObj(
    Tcl_Interp *interp,
    Tcl_Obj *valuePtr,
    Tcl_Obj *incrPtr)
{
    ClientData ptr1, ptr2;
    int type1, type2;
    mp_int value, incr;
    mp_err err;

    if (Tcl_IsShared(valuePtr)) {
	Tcl_Panic("%s called with shared object", "TclIncrObj");
    }







|












|









|










|







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
     * information.
     */

    iPtr->invokeCmdFramePtr = invoker;
    iPtr->invokeWord = word;
    TclSetByteCodeFromAny(interp, objPtr, NULL, NULL);
    iPtr->invokeCmdFramePtr = NULL;
    ByteCodeGetInternalRep(objPtr, &tclByteCodeType, codePtr);
    if (iPtr->varFramePtr->localCachePtr) {
	codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
	codePtr->localCachePtr->refCount++;
    }
    return codePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclIncrObj --
 *
 *	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 incremented value.
 *
 *----------------------------------------------------------------------
 */

int
TclIncrObj(
    Tcl_Interp *interp,
    Tcl_Obj *valuePtr,
    Tcl_Obj *incrPtr)
{
    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
    }

    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;

	/*
	 * Check for overflow.
	 */

	if (!Overflowing(w1, w2, sum)) {
	    TclSetIntObj(valuePtr, sum);







|







1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
    }

    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 = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2);

	/*
	 * Check for overflow.
	 */

	if (!Overflowing(w1, w2, sum)) {
	    TclSetIntObj(valuePtr, sum);
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
    Tcl_Interp *interp,
    ByteCode *codePtr,
    TEBCdata *tdPtr,
    const unsigned char *pc,
    int objc,
    Tcl_Obj **objv)
{
    int cmd;

    if (GetSrcInfoForPc(pc, codePtr, NULL, NULL, &cmd)) {
	TclArgumentBCEnter(interp, objv, objc, codePtr, &tdPtr->cmdFrame, cmd,
		pc - codePtr->codeStart);
    }
}








|







1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
    Tcl_Interp *interp,
    ByteCode *codePtr,
    TEBCdata *tdPtr,
    const unsigned char *pc,
    int objc,
    Tcl_Obj **objv)
{
    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
 *
 * 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 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
	    + (codePtr->maxStackDepth + codePtr->maxExceptDepth)
		* sizeof(void *);
    int 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







|
|









|


|







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
 *
 * Side effects:
 *	Almost certainly, depending on the ByteCode's instructions.
 *
 *----------------------------------------------------------------------
 */
#define	bcFramePtr	(&TD->cmdFrame)
#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;
    size_t size = sizeof(TEBCdata) - 1
	    + (codePtr->maxStackDepth + codePtr->maxExceptDepth)
		* sizeof(void *);
    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
    TclResetRewriteEnsemble(interp, 1);

    /*
     * Push the callback for bytecode execution
     */

    TclNRAddCallback(interp, TEBCresume, TD, /* pc */ NULL,
	    /* cleanup */ INT2PTR(0), 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[],
    Tcl_Interp *interp,
    int result)
{
    /*
     * Compiler cast directive - not a real variable.
     *	   Interp *iPtr = (Interp *) interp;
     */







|












|







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
    TclResetRewriteEnsemble(interp, 1);

    /*
     * Push the callback for bytecode execution
     */

    TclNRAddCallback(interp, TEBCresume, TD, /* pc */ NULL,
	    /* 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(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    /*
     * Compiler cast directive - not a real variable.
     *	   Interp *iPtr = (Interp *) interp;
     */
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
     * 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;
    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);
	fflush(stdout);
    }
#endif

    if (!pc) {
	/* bytecode is starting from scratch */
	pc = codePtr->codeStart;







|
|















|







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
     * 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;
    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=%" TCL_T_MODIFIER "d\n", CURR_DEPTH);
	fflush(stdout);
    }
#endif

    if (!pc) {
	/* bytecode is starting from scratch */
	pc = codePtr->codeStart;
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
	}

	/*
	 * Push the call's object result and continue execution with the next
	 * instruction.
	 */

	TRACE_WITH_OBJ(("%u => ... 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







|







2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
	}

	/*
	 * Push the call's object result and continue execution with the next
	 * instruction.
	 */

	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
#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);
	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);
	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);
	if (checkInterp) {
	    if (((codePtr->compileEpoch != iPtr->compileEpoch) ||
		 (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) {







|











|







|


|
|







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
#ifdef TCL_COMPILE_DEBUG
    /*
     * Skip the stack depth check if an expansion is in progress.
     */

    CHECK_STACK();
    if (traceInstructions) {
	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);
	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);
	if (checkInterp) {
	    if (((codePtr->compileEpoch != iPtr->compileEpoch) ||
		    (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
	}
	cleanup = 1;
	TRACE_APPEND(("\n"));
	goto processExceptionReturn;

    {
	CoroutineData *corPtr;
	int 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);
	    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),
			Tcl_GetString(OBJ_AT_TOS));
	    }
	    fflush(stdout);
	}
#endif
	yieldParameter = 0;
	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);
	    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);
	    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),
			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;

	TclSetTailcall(interp, valuePtr);

	iPtr->execEnvPtr = corPtr->eePtr;
	yieldParameter = (PTR2INT(NULL)+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);
	return TCL_OK;
    }

    case INST_TAILCALL: {
	Tcl_Obj *listPtr, *nsObjPtr;

	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);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

#ifdef TCL_COMPILE_DEBUG
	/* FIXME: What is the right thing to trace? */
	{







|










|









|
|





|













|










|










|
|












<

>

>

|

















|













|







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
	}
	cleanup = 1;
	TRACE_APPEND(("\n"));
	goto processExceptionReturn;

    {
	CoroutineData *corPtr;
	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",
		    (void *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

#ifdef TCL_COMPILE_DEBUG
	if (tclTraceExec >= 2) {
	    if (traceInstructions) {
		TRACE_APPEND(("YIELD...\n"));
	    } else {
		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 = 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",
		    (void *)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",
		    (void *)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, "%" 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').
	 */


	iPtr->execEnvPtr = corPtr->callerEEPtr;
	Tcl_IncrRefCount(valuePtr);
	TclSetTailcall(interp, valuePtr);
	corPtr->yieldPtr = valuePtr;
	iPtr->execEnvPtr = corPtr->eePtr;
	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,
		yieldParameter, NULL, NULL);
	return TCL_OK;
    }

    case INST_TAILCALL: {
	Tcl_Obj *listPtr, *nsObjPtr;

	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", (void *)NULL);
	    CACHE_STACK_INFO();
	    goto gotError;
	}

#ifdef TCL_COMPILE_DEBUG
	/* FIXME: What is the right thing to trace? */
	{
2593
2594
2595
2596
2597
2598
2599

2600
2601
2602

2603
2604
2605
2606

2607
2608
2609
2610
2611
2612
2613
	NEXT_INST_F(5, 0, 0);
    }
    break;

    case INST_STR_CONCAT1:

	opnd = TclGetUInt1AtPtr(pc+1);

	objResultPtr = TclStringCat(interp, opnd, &OBJ_AT_DEPTH(opnd-1),
		TCL_STRING_IN_PLACE);
	if (objResultPtr == NULL) {

	    TRACE_ERROR(interp);
	    goto gotError;
	}


	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,







>



>




>







2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
	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,
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
	 * 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));
	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));
	NEXT_INST_V(1, objc, 0);

    case INST_EXPAND_STKTOP: {
	int i;
	ptrdiff_t moved;


	/*
	 * 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.
	 */








|

















|



|
|
>







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
	 * 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 %" 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 %" TCL_SIZE_MODIFIER "d items\n", objc));
	NEXT_INST_V(1, objc, 0);

    case INST_EXPAND_STKTOP: {
	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

	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();



	    moved = GrowEvaluationStack(iPtr->execEnvPtr, length, 1)
		    - (Tcl_Obj **) TD;
	    if (moved) {
		/*
		 * 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);

		catchTop += moved;
		tosPtr += moved;
	    }
	}

	/*
	 * Expand the list at stacktop onto the stack; free the list. Knowing
	 * that it has a freeIntRepProc we use Tcl_DecrRefCount().
	 */







>
>
>
|
<
|






|

|
|







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

	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 *)
		    GrowEvaluationStack(iPtr->execEnvPtr, length, 1);

	    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 = newTD;

		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

    doInvocation:
	objv = &OBJ_AT_DEPTH(objc-1);
	cleanup = objc;

#ifdef TCL_COMPILE_DEBUG
	if (tclTraceExec >= 2) {
	    int i;

	    if (traceInstructions) {
		strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
		TRACE(("%u => call ", objc));
	    } else {
		fprintf(stdout, "%d: (%u) invoking ", iPtr->numLevels,
			(unsigned)(pc - codePtr->codeStart));
	    }
	    for (i = 0;  i < objc;  i++) {
		TclPrintObject(stdout, objv[i], 15);
		fprintf(stdout, " ");
	    }
	    fprintf(stdout, "\n");
	    fflush(stdout);







|



|

|
|







2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808

    doInvocation:
	objv = &OBJ_AT_DEPTH(objc-1);
	cleanup = objc;

#ifdef TCL_COMPILE_DEBUG
	if (tclTraceExec >= 2) {
	    Tcl_Size i;

	    if (traceInstructions) {
		strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
		TRACE(("%" TCL_SIZE_MODIFIER "d => call ", objc));
	    } else {
		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
	    ArgumentBCEnter(interp, codePtr, TD, pc, objc, objv);
	}

	DECACHE_STACK_INFO();

	pc += pcAdjustment;
	TEBC_YIELD();



	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;

	    if (traceInstructions) {
		strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
		TRACE(("%u => call (implementation %s) ", objc, O2S(objPtr)));
	    } else {
		fprintf(stdout,
			"%d: (%u) invoking (using implementation %s) ",
			iPtr->numLevels, (unsigned)(pc - codePtr->codeStart),
			O2S(objPtr));
	    }
	    for (i = 0;  i < objc;  i++) {
		if (i < opnd) {
		    fprintf(stdout, "<");
		    TclPrintObject(stdout, objv[i], 15);
		    fprintf(stdout, ">");







>
>
>
|

>









|



|


|
|







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
	    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,
		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) {
	    Tcl_Size i;

	    if (traceInstructions) {
		strncpy(cmdNameBuf, TclGetString(objv[0]), 20);
		TRACE(("%" TCL_Z_MODIFIER "u => call (implementation %s) ", objc, O2S(objPtr)));
	    } else {
		fprintf(stdout,
			"%" 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

	DECACHE_STACK_INFO();
	pc += 6;
	TEBC_YIELD();

	TclMarkTailcall(interp);
	TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
	Tcl_ListObjGetElements(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.
     *







|







2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902

	DECACHE_STACK_INFO();
	pc += 6;
	TEBC_YIELD();

	TclMarkTailcall(interp);
	TclNRAddCallback(interp, TclClearRootEnsemble, NULL, NULL, NULL, NULL);
	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
     *
     * 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;


    case INST_STORE_ARRAY4:
	opnd = TclGetUInt4AtPtr(pc+1);
	pcAdjustment = 5;
	goto doStoreArrayDirect;

    case INST_STORE_ARRAY1:







|
>







3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
     *
     * 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;
	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
	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) {
	    tosPtr--;
	    NEXT_INST_F((pcAdjustment+1), 0, 0);
	}
#else
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#endif
	Tcl_IncrRefCount(objResultPtr);







|







3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
	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) {
	    tosPtr--;
	    NEXT_INST_F((pcAdjustment+1), 0, 0);
	}
#else
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#endif
	Tcl_IncrRefCount(objResultPtr);
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
		part1Ptr, part2Ptr, valuePtr, storeFlags, opnd);
	CACHE_STACK_INFO();
	if (!objResultPtr) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
#ifndef TCL_COMPILE_DEBUG
	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:







|







3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
		part1Ptr, part2Ptr, valuePtr, storeFlags, opnd);
	CACHE_STACK_INFO();
	if (!objResultPtr) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
#ifndef TCL_COMPILE_DEBUG
	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
	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)
		!= TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_V(pcAdjustment, cleanup, 1);








|







3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
	if (Tcl_IsShared(objResultPtr)) {
	    Tcl_Obj *newValue = Tcl_DuplicateObj(objResultPtr);

	    TclDecrRefCount(objResultPtr);
	    varPtr->value.objPtr = objResultPtr = newValue;
	    Tcl_IncrRefCount(newValue);
	}
	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
	    } else {
		if (Tcl_IsShared(objResultPtr)) {
		    valueToAssign = Tcl_DuplicateObj(objResultPtr);
		    createdNewObj = 1;
		} else {
		    valueToAssign = objResultPtr;
		}
		if (Tcl_ListObjReplace(interp, valueToAssign, len, 0,
			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
     * common execution code.
     */

/*TODO: Consider more untangling here; merge with LOAD and STORE ? */

    {
	Tcl_Obj *incrPtr;







|








<


<

















|







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
	    } else {
		if (Tcl_IsShared(objResultPtr)) {
		    valueToAssign = Tcl_DuplicateObj(objResultPtr);
		    createdNewObj = 1;
		} else {
		    valueToAssign = objResultPtr;
		}
		if (TclListObjAppendElements(interp, valueToAssign,
			objc, objv) != TCL_OK) {
		    if (createdNewObj) {
			TclDecrRefCount(valueToAssign);
		    }
		    goto errorInLappendListPtr;
		}
	    }
	    DECACHE_STACK_INFO();

	    objResultPtr = TclPtrSetVarIdx(interp, varPtr, arrayPtr, part1Ptr,
		    part2Ptr, valueToAssign, TCL_LEAVE_ERR_MSG, opnd);

	    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 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
	cleanup = 0;
	varPtr = LOCAL(opnd);
	while (TclIsVarLink(varPtr)) {
	    varPtr = varPtr->value.linkPtr;
	}

	if (TclIsVarDirectModifyable(varPtr)) {
	    ClientData 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;

		    /*
		     * Overflow when (augend and sum have different sign) and
		     * (augend and increment have the same sign). This is
		     * encapsulated in the Overflowing macro.
		     */








|






|







3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
	cleanup = 0;
	varPtr = LOCAL(opnd);
	while (TclIsVarLink(varPtr)) {
	    varPtr = varPtr->value.linkPtr;
	}

	if (TclIsVarDirectModifyable(varPtr)) {
	    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 = (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
			TclNewIntObj(objResultPtr, w + increment);
			Tcl_IncrRefCount(objResultPtr);
			varPtr->value.objPtr = objResultPtr;
		    } else {
			objResultPtr = objPtr;

			/*
			 * We know the sum value is outside the long range;
			 * use macro form that doesn't range test again.
			 */

			TclSetIntObj(objPtr, w+increment);
		    }
		    goto doneIncr;
		}	/* end if (type == TCL_NUMBER_INT) */







|







3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
			TclNewIntObj(objResultPtr, w + increment);
			Tcl_IncrRefCount(objResultPtr);
			varPtr->value.objPtr = objResultPtr;
		    } else {
			objResultPtr = objPtr;

			/*
			 * 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
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
    doneIncr:
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#ifndef TCL_COMPILE_DEBUG
	if (*(pc+pcAdjustment) == INST_POP) {
	    NEXT_INST_V((pcAdjustment+1), cleanup, 0);
	}
#endif
	NEXT_INST_V(pcAdjustment, cleanup, 1);
    }

    /*







|







3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
    doneIncr:
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
#ifndef TCL_COMPILE_DEBUG
	if (pc[pcAdjustment] == INST_POP) {
	    NEXT_INST_V((pcAdjustment+1), cleanup, 0);
	}
#endif
	NEXT_INST_V(pcAdjustment, cleanup, 1);
    }

    /*
3911
3912
3913
3914
3915
3916
3917







































































3918
3919
3920
3921
3922
3923
3924
	TRACE_ERROR(interp);
	goto gotError;
    }
    break;

    /*
     *	   End of INST_UNSET instructions.







































































     * -----------------------------------------------------------------
     *	   Start of INST_ARRAY instructions.
     */

    case INST_ARRAY_EXISTS_IMM:
	opnd = TclGetUInt4AtPtr(pc+1);
	pcAdjustment = 5;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	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", (void *)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
		/*
		 * 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);
		CACHE_STACK_INFO();
		TRACE_ERROR(interp);
		goto gotError;
	    }
	    TclInitArrayVar(varPtr);
#ifdef TCL_COMPILE_DEBUG
	    TRACE_APPEND(("done\n"));







|







4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
		/*
		 * 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", (void *)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
    /*
     *	   End of variable linking instructions.
     * -----------------------------------------------------------------
     */

    case INST_JUMP1:
	opnd = TclGetInt1AtPtr(pc+1);
	TRACE(("%d => new pc %u\n", opnd,
		(unsigned)(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)));
	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. */







|
|





|
|







4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
    /*
     *	   End of variable linking instructions.
     * -----------------------------------------------------------------
     */

    case INST_JUMP1:
	opnd = TclGetInt1AtPtr(pc+1);
	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 %" 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
	    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)));
	    } 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)));
	    }
	}
#endif
	NEXT_INST_F(jmpOffset[b], 1, 0);
    }
    break;








|
|







|
|







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
	    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 %" 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 %" 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
	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)));
	    NEXT_INST_F(jumpOffset, 1, 0);
	} else {
	    TRACE_APPEND(("not found in table\n"));
	    NEXT_INST_F(5, 1, 0);
	}
    }
    break;







|
|







4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
	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 %" 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;
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
		    objResultPtr);
	}
	TRACE_WITH_OBJ(("=> "), objResultPtr);
	NEXT_INST_F(1, 0, 1);
    }
    break;
    case INST_INFO_LEVEL_NUM:
	TclNewIntObj(objResultPtr, 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) ;
		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);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	objResultPtr = Tcl_NewListObj(framePtr->objc, framePtr->objv);
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_F(1, 1, 1);
    }







|
















|









|







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
		    objResultPtr);
	}
	TRACE_WITH_OBJ(("=> "), objResultPtr);
	NEXT_INST_F(1, 0, 1);
    }
    break;
    case INST_INFO_LEVEL_NUM:
	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 (; ((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), (void *)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
	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);
	    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;

    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);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	contextPtr = (CallContext *)framePtr->clientData;

	/*
	 * Call out to get the name; it's expensive to compute but cached.







|

















|










|







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
	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), (void *)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;
	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", (void *)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
	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);
	    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;
	    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);
		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 ",
				    iPtr->numLevels,
				    (unsigned)(pc - codePtr->codeStart));
			}
			for (i = 0;  i < opnd;  i++) {
			    TclPrintObject(stdout, objv[i], 15);
			    fprintf(stdout, " ");
			}
			fprintf(stdout, "\n");
			fflush(stdout);







|












|







|














|

|







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
	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", (void *)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;
	    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", (void *)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, "%" TCL_SIZE_MODIFIER "d: (%" TCL_T_MODIFIER "d) invoking ",
				    iPtr->numLevels,
				    (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
		methodType = "destructor";
	    } else {
		methodType = "method";
	    }

	    TRACE_APPEND(("ERROR: \"%.30s\" not on reachable chain\n",
		    O2S(valuePtr)));
	    for (i=contextPtr->index ; i>=0 ; 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);
		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);
	    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);
	    CACHE_STACK_INFO();
	    goto gotError;
	}
	contextPtr = (CallContext *)framePtr->clientData;

	newDepth = contextPtr->index + 1;
	if (newDepth >= contextPtr->callPtr->numChain) {







|










|







|

















|







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
		methodType = "destructor";
	    } else {
		methodType = "method";
	    }

	    TRACE_APPEND(("ERROR: \"%.30s\" not on reachable chain\n",
		    O2S(valuePtr)));
	    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",
			(void *)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", (void *)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", (void *)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
		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);
	    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));
	    }
	    for (i = 0;  i < opnd;  i++) {
		TclPrintObject(stdout, objv[i], 15);
		fprintf(stdout, " ");
	    }
	    fprintf(stdout, "\n");
	    fflush(stdout);







|









|
|







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
		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", (void *)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, "%" 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
	    oPtr->flags &= ~FILTER_HANDLING;
	}

	{
	    Method *const mPtr =
		    contextPtr->callPtr->chain[newDepth].mPtr;


	    return 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);







>
|
>
>
>







4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
	    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,
			(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);
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
     *     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;
	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));
	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)));
























	/*
	 * Extract the desired list element.
	 */





	if ((TclListObjGetElements(interp, valuePtr, &objc, &objv) == TCL_OK)
		&& !TclHasIntRep(value2Ptr, &tclListType)) {




	    int code;






	    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);
	}



	objResultPtr = TclLindexList(interp, valuePtr, value2Ptr);



	if (!objResultPtr) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}

	/*
	 * Stash the list element on the stack.







|




















|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>
>
>
>
|
|
>
>
>
>
|

>
>
>
>
>
|
|
>
|
|
|
|
|
|
|
|
|
|
>
>

>
>
>







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
     *     End of TclOO support instructions.
     * -----------------------------------------------------------------
     *	   Start of INST_LIST and related instructions.
     */

    {
	int numIndices, nocase, match, cflags;
	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(("%" 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)
		    && (!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, 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
	TRACE(("\"%.30s\" %d => ", O2S(valuePtr), opnd));

	/*
	 * Get the contents of the list, making sure that it really is a list
	 * in the process.
	 */


























	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) {
	    objResultPtr = objv[index];
	} else {
	    TclNewObj(objResultPtr);
	}



	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.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|




>
>







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
	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 >= 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
	valuePtr = POP_OBJECT();
	Tcl_DecrRefCount(valuePtr); /* This one should be done here */

	/*
	 * Compute the new variable value.
	 */







	objResultPtr = TclLsetFlat(interp, valuePtr, numIndices,
		&OBJ_AT_DEPTH(numIndices), OBJ_AT_TOS);

	if (!objResultPtr) {

	    TRACE_ERROR(interp);
	    goto gotError;
	}

	/*
	 * Set result.
	 */

	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







>
>
>
>
>
>
|

>

>







|







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
	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);
	}
	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

	/*
	 * 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) {
	    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.) */







|







5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019

	/*
	 * 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) {
	    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
4937
	    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) {
	    toIdx = objc - 1;
	}

	assert (toIdx < (size_t)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);







	objResultPtr = TclListObjRange(valuePtr, fromIdx, toIdx);








	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 (TclListObjLength(interp, value2Ptr, &length) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	match = 0;
	if (length > 0) {
	    int i = 0;
	    Tcl_Obj *o;


	    /*
	     * 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);
	}


	if (*pc == INST_LIST_NOT_IN) {
	    match = !match;
	}

	TRACE_APPEND(("%d\n", match));








|



|











>
>
>
>
>
>
|
|
>
>
>
>
>
>
>








|
|
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
>

|
|
|

|
>
>
>
>
>
>
>
>
>
|
>
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
>







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
	    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 >= objc) {
	    toIdx = objc - 1;
	}

	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(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) {
                Tcl_Size i = 0;
                Tcl_Obj *o;
                int isAbstractList = TclObjTypeHasProc(value2Ptr,indexProc) != NULL;

                /*
                 * An empty list doesn't match anything.
                 */

                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
		TRACE_ERROR(interp);
		goto gotError;
	    }
	    TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
	    NEXT_INST_F(1, 1, 0);
	}
















































































    /*
     *	   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:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|







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
		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.
	 */

    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
	    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);
	    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);
	    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);
	    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.
	 */

	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) {
	    TclNewObj(objResultPtr);
	} else if (TclIsPureByteArray(valuePtr)) {
	    objResultPtr = Tcl_NewByteArrayObj(
		    Tcl_GetByteArrayFromObj(valuePtr, 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,
		    &fromIdx) != TCL_OK) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	if (TclGetIntForIndexM(interp, OBJ_AT_TOS, slength,
		    &toIdx) != TCL_OK) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	CACHE_STACK_INFO();

	if (fromIdx == 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);
	} else {
	    TclNewObj(objResultPtr);
	}
	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) {
	    fromIdx = TCL_INDEX_START;
	}

	if (fromIdx + 1 <= toIdx + 1) {
	    objResultPtr = Tcl_GetRange(valuePtr, fromIdx, toIdx);
	} else {
	emptyRange:
	    TclNewObj(objResultPtr);
	}
	TRACE_APPEND(("%.30s\n", O2S(objResultPtr)));
	NEXT_INST_F(9, 1, 1);

    {
	Tcl_UniChar *ustring1, *ustring2, *ustring3, *end, *p;
	size_t 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,
		    &fromIdx) != TCL_OK
	    || TclGetIntForIndexM(interp, OBJ_AT_TOS, slength,
		    &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) ||
		(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 (toIdx + 1 > slength + 1) {
	    toIdx = slength;
	}

	if ((fromIdx == TCL_INDEX_START) && (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,







|
















|
















|










|











|



|
















<
<
<













|
<




|
<






|
<
<
<
<
<
<
|

|



















<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
<
<
|
<
<

<
|






|









|
<
|
<











|
<
<





|
|


|



|







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
	    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);
	    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);
	    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);
	    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 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 < 0 || index >= slength) {
	    TclNewObj(objResultPtr);
	} else if (TclIsPureByteArray(valuePtr)) {
	    objResultPtr = Tcl_NewByteArrayObj(
		    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);



		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, &fromIdx) != TCL_OK) {

	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	if (TclGetIntForIndexM(interp, OBJ_AT_TOS, slength, &toIdx) != TCL_OK) {

	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	CACHE_STACK_INFO();

	if (toIdx == TCL_INDEX_NONE) {






	    TclNewObj(objResultPtr);
	} else {
	    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. */










	toIdx = TclIndexDecode(toIdx, slength - 1);

















	fromIdx = TclIndexDecode(fromIdx, slength - 1);
	if (toIdx == TCL_INDEX_NONE) {


	    TclNewObj(objResultPtr);


	} else {

	    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;
	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, &fromIdx) != TCL_OK

		|| TclGetIntForIndexM(interp, OBJ_AT_TOS, slength, &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 < 0) || (fromIdx > slength) || (toIdx < fromIdx)) {


	    TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr)));
	    TclDecrRefCount(value3Ptr);
	    NEXT_INST_F(1, 0, 0);
	}

	if (fromIdx < 0) {
	    fromIdx = 0;
	}

	if (toIdx > slength) {
	    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
	if (value3Ptr == value2Ptr) {
	    objResultPtr = valuePtr;
	    goto doneStringMap;
	} else if (valuePtr == value2Ptr) {
	    objResultPtr = value3Ptr;
	    goto doneStringMap;
	}
	ustring1 = TclGetUnicodeFromObj(valuePtr, &slength);
	if (slength == 0) {
	    objResultPtr = valuePtr;
	    goto doneStringMap;
	}
	ustring2 = TclGetUnicodeFromObj(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);

	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 (p != ustring1) {
		    TclAppendUnicodeToObj(objResultPtr, p, ustring1-p);
		    p = ustring1 + length2;
		} else {
		    p += length2;
		}
		ustring1 = p - 1;

		TclAppendUnicodeToObj(objResultPtr, ustring3, length3);
	    }
	}
	if (p != ustring1) {
	    /*
	     * Put the rest of the unmapped chars onto result.
	     */

	    TclAppendUnicodeToObj(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",
		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);

	TRACE(("%.20s %.20s => %d\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);
	match = 1;
	if (slength > 0) {
	    int ch;
	    end = ustring1 + slength;
	    for (p=ustring1 ; p<end ; ) {
		p += TclUniCharToUCS4(p, &ch);
		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)) {
	    Tcl_UniChar *ustring1, *ustring2;

	    ustring1 = TclGetUnicodeFromObj(valuePtr, &slength);
	    ustring2 = TclGetUnicodeFromObj(value2Ptr, &length2);
	    match = TclUniCharMatch(ustring1, slength, ustring2, length2,
		    nocase);
	} else if (TclIsPureByteArray(valuePtr) && !nocase) {
	    unsigned char *bytes1, *bytes2;
	    size_t wlen1 = 0, wlen2 = 0;

	    bytes1 = TclGetByteArrayFromObj(valuePtr, &wlen1);
	    bytes2 = TclGetByteArrayFromObj(value2Ptr, &wlen2);
	    match = TclByteArrayMatch(bytes1, wlen1, bytes2, wlen2, 0);
	} else {
	    match = Tcl_StringCaseMatch(TclGetString(valuePtr),
		    TclGetString(value2Ptr), nocase);
	}

	/*







|




|











|





|
>
>
|
|

|






|







|









|




|

|








|





|




















|
|


|
|


|

|

|
|







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
	if (value3Ptr == value2Ptr) {
	    objResultPtr = valuePtr;
	    goto doneStringMap;
	} else if (valuePtr == value2Ptr) {
	    objResultPtr = value3Ptr;
	    goto doneStringMap;
	}
	ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &slength);
	if (slength == 0) {
	    objResultPtr = valuePtr;
	    goto doneStringMap;
	}
	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 = Tcl_GetUnicodeFromObj(value3Ptr, &length3);

	objResultPtr = Tcl_NewUnicodeObj(ustring1, 0);
	p = ustring1;
	end = ustring1 + slength;
	for (; ustring1 < end; ustring1++) {
	    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) {
		    Tcl_AppendUnicodeToObj(objResultPtr, p, ustring1-p);
		    p = ustring1 + length2;
		} else {
		    p += length2;
		}
		ustring1 = p - 1;

		Tcl_AppendUnicodeToObj(objResultPtr, ustring3, length3);
	    }
	}
	if (p != ustring1) {
	    /*
	     * Put the rest of the unmapped chars onto result.
	     */

	    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 => %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, TCL_SIZE_MAX - 1);

	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 = Tcl_GetUnicodeFromObj(valuePtr, &slength);
	match = 1;
	if (slength > 0) {
	    int ch;
	    end = ustring1 + slength;
	    for (p=ustring1 ; p<end ; ) {
		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 (TclHasInternalRep(valuePtr, &tclStringType)
		|| TclHasInternalRep(value2Ptr, &tclStringType)) {
	    Tcl_UniChar *ustring1, *ustring2;

	    ustring1 = Tcl_GetUnicodeFromObj(valuePtr, &slength);
	    ustring2 = Tcl_GetUnicodeFromObj(value2Ptr, &length2);
	    match = TclUniCharMatch(ustring1, slength, ustring2, length2,
		    nocase);
	} else if (TclIsPureByteArray(valuePtr) && TclIsPureByteArray(value2Ptr) && !nocase) {
	    unsigned char *bytes1, *bytes2;
	    Tcl_Size wlen1 = 0, wlen2 = 0;

	    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
	 * 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;

    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);







|







5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
	 * Peep-hole optimisation: if you're about to jump, do jump from here.
	 */

	JUMP_PEEPHOLE_F(match, 2, 2);

    {
	const char *string1, *string2;
	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
    /*
     *	   End of string-related instructions.
     * -----------------------------------------------------------------
     *	   Start of numeric operator instructions.
     */

    {
	ClientData 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:







|






<
<
<
<
<
<
<
<







5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777








5778
5779
5780
5781
5782
5783
5784
    /*
     *	   End of string-related instructions.
     * -----------------------------------------------------------------
     *	   Start of numeric operator instructions.
     */

    {
	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;








	}
	TclNewIntObj(objResultPtr, type1);
	TRACE(("\"%.20s\" => %d\n", O2S(OBJ_AT_TOS), type1));
	NEXT_INST_F(1, 1, 1);

    case INST_EQ:
    case INST_NEQ:
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
		     */

		    if ((wResult < 0 || (wResult == 0 &&
			    ((w1 < 0 && w2 > 0) || (w1 > 0 && w2 < 0)))) &&
			    (wResult * w2 != w1)) {
			wResult -= 1;
		    }
		    wResult = w1 - w2*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);
		    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))) {
			/*
			 * We assume that INT_MAX is much larger than the
			 * number of bits in a long. This is a pretty safe
			 * assumption, given that the former is usually around
			 * 4e9 and the latter 32 or 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.
		     */

		    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);
		    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)));







|
>












|













|


|

|













|















|







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
		     */

		    if ((wResult < 0 || (wResult == 0 &&
			    ((w1 < 0 && w2 > 0) || (w1 > 0 && w2 < 0)))) &&
			    (wResult * w2 != w1)) {
			wResult -= 1;
		    }
		    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",
			    (void *)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(w1))) {
			/*
			 * We assume that INT_MAX is much larger than the
			 * number of bits in a Tcl_WideInt. This is a pretty safe
			 * assumption, given that the former is usually around
			 * 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 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",
			    (void *)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
		     */

		    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);
		    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.
		     */

		    if ((size_t) shift < CHAR_BIT*sizeof(long) && (w1 != 0)
			    && !((w1>0 ? w1 : ~w1) &
				-(1L<<(CHAR_BIT*sizeof(long) - 1 - shift)))) {
			wResult = w1 << shift;
			goto wideResultOfArithmetic;
		    }
		}

		/*
		 * Too large; need to use the broken-out function.
		 */







|







|


|

|
|







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
		     */

		    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", (void *)NULL);
		    CACHE_STACK_INFO();
#endif /* ERROR_CODE_FOR_EARLY_DETECTED_ARITH_ERROR */
		    goto gotError;
		} else {
		    int shift = (int) w2;

		    /*
		     * Handle shifts within the native Tcl_WideInt range.
		     */

		    if (((size_t)shift < CHAR_BIT*sizeof(w1))
			    && !((w1>0 ? w1 : ~w1) &
				-((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.
		 */
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

	    objResultPtr = value2Ptr;
	    NEXT_INST_F(1, 2, 1);
	}
#endif

	/*
	 * Handle (long,long) 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;
		/*
		 * Check for overflow.
		 */

		if (Overflowing(w1, w2, wResult)) {
		    goto overflow;
		}
		goto wideResultOfArithmetic;

	    case INST_SUB:
		wResult = w1 - 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







|









|










|







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

	    objResultPtr = value2Ptr;
	    NEXT_INST_F(1, 2, 1);
	}
#endif

	/*
	 * 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 = (Tcl_WideInt)((Tcl_WideUInt)w1 + (Tcl_WideUInt)w2);
		/*
		 * Check for overflow.
		 */

		if (Overflowing(w1, w2, wResult)) {
		    goto overflow;
		}
		goto wideResultOfArithmetic;

	    case INST_SUB:
		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
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
	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
	     * the string so we do not copy it.
	     */

	    char *savedString = valuePtr->bytes;

	    valuePtr->bytes = NULL;
	    objResultPtr = Tcl_DuplicateObj(valuePtr);







|







6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
	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 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
    /*
     *	   End of numeric operator instructions.
     * -----------------------------------------------------------------
     */

    case INST_TRY_CVT_TO_BOOLEAN:
	valuePtr = OBJ_AT_TOS;
	if (TclHasIntRep(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);







|







6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
    /*
     *	   End of numeric operator instructions.
     * -----------------------------------------------------------------
     */

    case INST_TRY_CVT_TO_BOOLEAN:
	valuePtr = OBJ_AT_TOS;
	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
	TRACE(("=> CONTINUE!\n"));
	goto processExceptionReturn;

    {
	ForeachInfo *infoPtr;
	Tcl_Obj *listPtr, **elements;
	ForeachVarList *varListPtr;
	int numLists, listLen, numVars;
	int listTmpDepth;
	size_t iterNum, iterMax, iterTmp;
	int varIndex, valIndex, j;
	long i;

    case INST_FOREACH_START:
	/*
	 * Initialize the data for the looping construct, pushing the
	 * corresponding Tcl_Objs to the stack.
	 */








|
<
|
|
<







6475
6476
6477
6478
6479
6480
6481
6482

6483
6484

6485
6486
6487
6488
6489
6490
6491
	TRACE(("=> CONTINUE!\n"));
	goto processExceptionReturn;

    {
	ForeachInfo *infoPtr;
	Tcl_Obj *listPtr, **elements;
	ForeachVarList *varListPtr;
	Tcl_Size numLists, listLen, numVars, listTmpDepth;

	Tcl_Size iterNum, iterMax, iterTmp;
	Tcl_Size varIndex, valIndex, i, j;


    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

	iterMax = 0;
	listTmpDepth = numLists-1;
	for (i = 0;  i < numLists;  i++) {
	    varListPtr = infoPtr->varLists[i];
	    numVars = varListPtr->numVars;
	    listPtr = OBJ_AT_DEPTH(listTmpDepth);

	    if (TclListObjLength(interp, listPtr, &listLen) != TCL_OK) {

		TRACE_APPEND(("ERROR converting list %ld, \"%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);







>

>
|







6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517

	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 %" 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
	/*
	 * Jump directly to the INST_FOREACH_STEP instruction; the C code just
	 * falls through.
	 */

	pc += 5 - infoPtr->loopCtTemp;

    case INST_FOREACH_STEP:
	/*
	 * "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) {

	    /*
	     * 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;


		listPtr = OBJ_AT_DEPTH(listTmpDepth);







		TclListObjGetElements(interp, listPtr, &listLen, &elements);








		valIndex = (iterNum * numVars);
		for (j = 0;  j < numVars;  j++) {
		    if (valIndex >= listLen) {
			TclNewObj(valuePtr);
		    } else {


			valuePtr = elements[valIndex];














		    }

		    varIndex = varListPtr->varIndexes[j];
		    varPtr = LOCAL(varIndex);
		    while (TclIsVarLink(varPtr)) {
			varPtr = varPtr->value.linkPtr;
		    }







|




















>











>


>
>
>
>
>
>
>
|
>
>
>
>
>
>
>






>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	/*
	 * Jump directly to the INST_FOREACH_STEP instruction; the C code just
	 * falls through.
	 */

	pc += 5 - infoPtr->loopCtTemp;

    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(
			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];
			} 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
			    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",
				    varIndex, O2S(Tcl_GetObjResult(interp))));
			    goto gotError;
			}
			CACHE_STACK_INFO();
		    }
		    valIndex++;
		}







|







6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
			    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 %" 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
	 *   - 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));

	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));
	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)));
	NEXT_INST_F(1, 0, 0);
    break;

    case INST_PUSH_RESULT:
	objResultPtr = Tcl_GetObjResult(interp);
	TRACE_WITH_OBJ(("=> "), objResultPtr);








|














|
|
|
|









|







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
	 *   - 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 %" 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) = (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=%" 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

    /*
     * -----------------------------------------------------------------
     *	   Start of dictionary-related instructions.
     */

    {
	int opnd2, allocateDict, done, i, allocdict;

	Tcl_Obj *dictPtr, *statePtr, *keyPtr, *listPtr, *varNamePtr, *keysPtr;
	Tcl_Obj *emptyPtr, **keyPtrPtr;
	Tcl_DictSearch *searchPtr;
	DictUpdateInfo *duiPtr;

    case INST_DICT_VERIFY:

	dictPtr = OBJ_AT_TOS;
	TRACE(("\"%.30s\" => ", O2S(dictPtr)));
	if (Tcl_DictObjSize(interp, dictPtr, &done) != 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));







|
>





|
>


|






>







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

    /*
     * -----------------------------------------------------------------
     *	   Start of dictionary-related instructions.
     */

    {
	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: {
	Tcl_Size size;
	dictPtr = OBJ_AT_TOS;
	TRACE(("\"%.30s\" => ", O2S(dictPtr)));
	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
	}
	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);
	    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:







|







6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
	}
	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), (void *)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
	    TclDecrRefCount(dictPtr);
	    if (objResultPtr == NULL) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
#ifndef TCL_COMPILE_DEBUG
	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:







|







6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
	    TclDecrRefCount(dictPtr);
	    if (objResultPtr == NULL) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
#ifndef TCL_COMPILE_DEBUG
	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
	    TclDecrRefCount(dictPtr);
	    if (objResultPtr == NULL) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
#ifndef TCL_COMPILE_DEBUG
	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
	     * to drop the refcount [Tcl Bug 9b352768e6].
	     */

	    Tcl_DecrRefCount(dictPtr);
	    Tcl_Free(searchPtr);
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	{
	    Tcl_ObjIntRep ir;
	    TclNewObj(statePtr);
	    ir.twoPtrValue.ptr1 = searchPtr;
	    ir.twoPtrValue.ptr2 = dictPtr;
	    Tcl_StoreIntRep(statePtr, &dictIteratorType, &ir);
	}
	varPtr = LOCAL(opnd);
	if (varPtr->value.objPtr) {
	    if (TclHasIntRep(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;

	    if (statePtr &&
		    (irPtr = TclFetchIntRep(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
	 * 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);








|













<


|









|



|



|













|


|



















|







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
	    TclDecrRefCount(dictPtr);
	    if (objResultPtr == NULL) {
		TRACE_ERROR(interp);
		goto gotError;
	    }
	}
#ifndef TCL_COMPILE_DEBUG
	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 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_ObjInternalRep ir;
	    TclNewObj(statePtr);
	    ir.twoPtrValue.ptr1 = searchPtr;
	    ir.twoPtrValue.ptr2 = dictPtr;
	    Tcl_StoreInternalRep(statePtr, &dictIteratorType, &ir);
	}
	varPtr = LOCAL(opnd);
	if (varPtr->value.objPtr) {
	    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_ObjInternalRep *irPtr;

	    if (statePtr &&
		    (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 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
	}
	Tcl_IncrRefCount(dictPtr);
	if (TclListObjGetElements(interp, OBJ_AT_TOS, &length,
		&keyPtrPtr) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	if ((size_t)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);







|







7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
	}
	Tcl_IncrRefCount(dictPtr);
	if (TclListObjGetElements(interp, OBJ_AT_TOS, &length,
		&keyPtrPtr) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	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);
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
     * -----------------------------------------------------------------
     */

    case INST_CLOCK_READ:
	{			/* Read the wall clock */
	    Tcl_WideInt wval;
	    Tcl_Time now;
	    switch(TclGetUInt1AtPtr(pc+1)) {
	    case 0:		/* clicks */
#ifdef TCL_WIDE_CLICKS
		wval = TclpGetWideClicks();
#else
		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);







|




|




|



|



|







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
     * -----------------------------------------------------------------
     */

    case INST_CLOCK_READ:
	{			/* Read the wall clock */
	    Tcl_WideInt wval;
	    Tcl_Time now;
	    switch (TclGetUInt1AtPtr(pc+1)) {
	    case 0:		/* clicks */
#ifdef TCL_WIDE_CLICKS
		wval = TclpGetWideClicks();
#else
		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);
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
	    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",
			StringForResultCode(result),
			rangePtr->codeOffset, rangePtr->breakOffset));
		NEXT_INST_F(0, 0, 0);
	    }
	    if (rangePtr->continueOffset == -1) {
		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",
		    StringForResultCode(result),
		    rangePtr->codeOffset, rangePtr->continueOffset));
	    NEXT_INST_F(0, 0, 0);
	}
#ifdef TCL_COMPILE_DEBUG
	if (traceInstructions) {
	    objPtr = Tcl_GetObjResult(interp);







|




|






|







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
	    while (cleanup--) {
		valuePtr = POP_OBJECT();
		TclDecrRefCount(valuePtr);
	    }
	    if (result == TCL_BREAK) {
		result = TCL_OK;
		pc = (codePtr->codeStart + rangePtr->breakOffset);
		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 == 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 %" 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
	 * 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);
	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);
	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);
	CACHE_STACK_INFO();

	/*
	 * Almost all error paths feed through here rather than assigning to
	 * result themselves (for a small but consistent saving).
	 */








|






|













|







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
	 * 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", (void *)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", (void *)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", (void *)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

    checkForCatch:
	if (iPtr->execEnvPtr->rewind) {
	    goto abnormalReturn;
	}
	if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
	    const unsigned char *pcBeg;
	    size_t 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)) {
		break;
	    }
	    POP_TAUX_OBJ();
	}

	/*
	 * We must not catch if the script in progress has been canceled with







|
















|
|







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

    checkForCatch:
	if (iPtr->execEnvPtr->rewind) {
	    goto abnormalReturn;
	}
	if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) {
	    const unsigned char *pcBeg;
	    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)
		    && (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
	 * "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) {
	    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);
	}
#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.







|





|
|
|
|







7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
	 * "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 > PTR2INT(*catchTop)) {
	    valuePtr = POP_OBJECT();
	    TclDecrRefCount(valuePtr);
	}
#ifdef TCL_COMPILE_DEBUG
	if (traceInstructions) {
	    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
	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);
	    Tcl_Panic("TclNRExecuteByteCode execution failure: end stack top < start stack top");
	}
	CLANG_ASSERT(bcFramePtr);
    }

    iPtr->cmdFramePtr = bcFramePtr->nextPtr;
    TclReleaseByteCode(codePtr);







|
|
|
|







7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
	while (tosPtr > initTosPtr) {
	    objPtr = POP_OBJECT();
	    Tcl_DecrRefCount(objPtr);
	}

	if (tosPtr < initTosPtr) {
	    fprintf(stderr,
		    "\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

     * case INST_START_CMD:
     */

	instStartCmdFailed:
	{
	    const char *bytes;
	    size_t xxx1length;

	    xxx1length = 0;

	    if (TclInterpReady(interp) == TCL_ERROR) {
		goto gotError;
	    }








|







7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784

     * case INST_START_CMD:
     */

	instStartCmdFailed:
	{
	    const char *bytes;
	    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
#undef auxObjList
#undef catchTop
#undef TCONST
#undef esPtr

static int
FinalizeOONext(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    CallContext *contextPtr = (CallContext *)data[1];

    /*







|







7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
#undef auxObjList
#undef catchTop
#undef TCONST
#undef esPtr

static int
FinalizeOONext(
    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
    contextPtr->skip = PTR2INT(data[3]);
    contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    return result;
}

static int
FinalizeOONextFilter(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    CallContext *contextPtr = (CallContext *)data[1];

    /*







|







7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
    contextPtr->skip = PTR2INT(data[3]);
    contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    return result;
}

static int
FinalizeOONextFilter(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    CallContext *contextPtr = (CallContext *)data[1];

    /*
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
    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);		\
	return NULL;				\
    }
#define BIG_RESULT(b) \
    if (Tcl_IsShared(valuePtr)) {		\
	return Tcl_NewBignumObj(b);		\
    } else {					\
	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;
    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;

    (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 */







|






|












|





|
|







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
    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));		\
	return NULL;				\
    }
#define BIG_RESULT(b) \
    if (Tcl_IsShared(valuePtr)) {		\
	return Tcl_NewBignumObj(b);		\
    } else {					\
	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;
    void *ptr1, *ptr2;
    double d1, d2, dResult;
    Tcl_WideInt w1, w2, wResult;
    mp_int big1, big2, bigResult, bigRemainder;
    Tcl_Obj *objResultPtr;
    int invalid, zero;
    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
		wQuotient = w1 / w2;

		/*
		 * Force Tcl's integer division rules.
		 * TODO: examine for logic simplification
		 */

		if (((wQuotient < (Tcl_WideInt) 0)
			|| ((wQuotient == (Tcl_WideInt) 0)
			&& ((w1 < 0 && w2 > 0)
			|| (w1 > 0 && w2 < 0))))
			&& (wQuotient * w2 != w1)) {
		    wQuotient -= (Tcl_WideInt) 1;
		}
		wRemainder = w1 - w2*wQuotient;

		WIDE_RESULT(wRemainder);
	    }

	    Tcl_TakeBignumFromObj(NULL, value2Ptr, &big2);

	    /* TODO: internals intrusion */
	    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);







|
|



|

|
>






|







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
		wQuotient = w1 / w2;

		/*
		 * Force Tcl's integer division rules.
		 * TODO: examine for logic simplification
		 */

		if (((wQuotient < 0)
			|| ((wQuotient == 0)
			&& ((w1 < 0 && w2 > 0)
			|| (w1 > 0 && w2 < 0))))
			&& (wQuotient * w2 != w1)) {
		    wQuotient -= 1;
		}
		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)) {
		/*
		 * 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
	     */

	    mp_clear(&big2);
	    return NULL;
	}
	Tcl_GetBignumFromObj(NULL, valuePtr, &big1);
	Tcl_GetBignumFromObj(NULL, value2Ptr, &big2);
	err = mp_init_multi(&bigResult, &bigRemainder, 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.
	     */







|







8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
	     */

	    mp_clear(&big2);
	    return NULL;
	}
	Tcl_GetBignumFromObj(NULL, valuePtr, &big1);
	Tcl_GetBignumFromObj(NULL, value2Ptr, &big2);
	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
	    /*
	     * 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)
			& -(((Tcl_WideInt)1)
			<< (CHAR_BIT*sizeof(Tcl_WideInt) - 1 - shift)))) {
		    WIDE_RESULT(w1 << shift);
		}
	    }
	} else {
	    /*
	     * Quickly force large right shifts to 0 or -1.
	     */








|
<
|
|







8179
8180
8181
8182
8183
8184
8185
8186

8187
8188
8189
8190
8191
8192
8193
8194
8195
	    /*
	     * 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) & -(

			((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
		 * Anything to the first power is itself
		 */

		return NULL;
	    }

	    negativeExponent = (w2 < 0);
	    oddExponent = (int) (w2 & (Tcl_WideInt)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);
	}







|







8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
		 * Anything to the first power is itself
		 */

		return NULL;
	    }

	    negativeExponent = (w2 < 0);
	    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
		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
	 * 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);
	    }
	    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));
	    }
	    goto overflowExpon;
	}
	if (w2 - 2 < (long)MaxBase64Size
		&& w1 <=  MaxBase64[w2 - 2]
		&& w1 >= -MaxBase64[w2 - 2]) {
	    /*







|


















|
|










|
|







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
		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 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);
	    }
	    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));
	    }
	    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
		WIDE_RESULT(wResult);
	    }
	}

    overflowExpon:

	if ((TclGetWideIntFromObj(NULL, value2Ptr, &w2) != TCL_OK)
		|| (value2Ptr->typePtr != &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) {

	    err = mp_expt_u32(&big1, (unsigned int)w2, &bigResult);
	}
	if (err != MP_OKAY) {
	    return OUT_OF_MEMORY;
	}
	mp_clear(&big1);
	BIG_RESULT(&bigResult);
    }







|








>
|







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
		WIDE_RESULT(wResult);
	    }
	}

    overflowExpon:

	if ((TclGetWideIntFromObj(NULL, value2Ptr, &w2) != TCL_OK)
		|| !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 = 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

	doubleResult:
#ifndef ACCEPT_NAN
	    /*
	     * Check now for IEEE floating-point error.
	     */

	    if (TclIsNaN(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))
		{
		    /*
		     * 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))
		{
		    /*
		     * 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







|












|
|
<











|
|
<







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

	doubleResult:
#ifndef ACCEPT_NAN
	    /*
	     * Check now for IEEE floating-point error.
	     */

	    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 = (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 = (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
8442
8443
8444
8445
8446
8447
8448
8449
8450
8451
8452
8453
8454
8455
8456
}

static Tcl_Obj *
ExecuteExtendedUnaryMathOp(
    int opcode,			/* What operation to perform. */
    Tcl_Obj *valuePtr)		/* The operand on the stack. */
{
    ClientData ptr;
    int type;
    Tcl_WideInt w;
    mp_int big;
    Tcl_Obj *objResultPtr;
    mp_err err = MP_OKAY;

    (void) GetNumberFromObj(NULL, valuePtr, &ptr, &type);







|







8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
8716
8717
}

static Tcl_Obj *
ExecuteExtendedUnaryMathOp(
    int opcode,			/* What operation to perform. */
    Tcl_Obj *valuePtr)		/* The operand on the stack. */
{
    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

int
TclCompareTwoNumbers(
    Tcl_Obj *valuePtr,
    Tcl_Obj *value2Ptr)
{
    int type1 = TCL_NUMBER_NAN, type2 = TCL_NUMBER_NAN, compare;
    ClientData 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
	     * converted to double without loss of precision, then compare as
	     * doubles.
	     */

	    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.







|




















|




|







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

int
TclCompareTwoNumbers(
    Tcl_Obj *valuePtr,
    Tcl_Obj *value2Ptr)
{
    int type1 = TCL_NUMBER_NAN, type2 = TCL_NUMBER_NAN, compare;
    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 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
		    || 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

	    if (d2 < (double)WIDE_MIN) {
		return MP_GT;
	    }
	    if (d2 > (double)WIDE_MAX) {
		return MP_LT;
	    }
	    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;







|







8832
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846

	    if (d2 < (double)WIDE_MIN) {
		return MP_GT;
	    }
	    if (d2 > (double)WIDE_MAX) {
		return MP_LT;
	    }
	    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
	    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) {
		goto doubleCompare;
	    }
	    if (d1 < (double)WIDE_MIN) {
		return MP_LT;
	    }
	    if (d1 > (double)WIDE_MAX) {
		return MP_GT;
	    }
	    w1 = (Tcl_WideInt) d1;
	    goto wideCompare;
	case TCL_NUMBER_BIG:
	    if (TclIsInfinite(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)
		    && 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)) {
		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)
		    && modf(d2, &tmp) != 0.0) {
		d1 = TclBignumToDouble(&big1);
		mp_clear(&big1);
		goto doubleCompare;
	    }
	    Tcl_InitBignumFromDouble(NULL, d2, &big2);
	    goto bigCompare;







|








|


|












|



















|









|







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
	    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) {
		goto doubleCompare;
	    }
	    if (d1 < (double)WIDE_MIN) {
		return MP_LT;
	    }
	    if (d1 > (double)WIDE_MAX) {
		return MP_GT;
	    }
	    w1 = (Tcl_WideInt)d1;
	    goto wideCompare;
	case TCL_NUMBER_BIG:
	    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(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 (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(Tcl_WideInt)
		    && modf(d2, &tmp) != 0.0) {
		d1 = TclBignumToDouble(&big1);
		mp_clear(&big1);
		goto doubleCompare;
	    }
	    Tcl_InitBignumFromDouble(NULL, d2, &big2);
	    goto bigCompare;
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

    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",
	    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",
	    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)),
	    codePtr->numCodeBytes,
	    (unsigned long) (codePtr->numLitObjects * sizeof(Tcl_Obj *)),
	    (unsigned long) (codePtr->numExceptRanges*sizeof(ExceptionRange)),
	    (unsigned long) (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",
		procPtr, procPtr->refCount, procPtr->numArgs,
		procPtr->numCompiledLocals);
    }
}
#endif /* TCL_COMPILE_DEBUG */

/*







|










|
>
|
|

|
|
|




|







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

    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",
	    codePtr, codePtr->refCount, codePtr->compileEpoch, iPtr,
	    iPtr->compileEpoch);
    fprintf(stdout, "  Source: ");
    TclPrintSource(stdout, codePtr->source, 60);

    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 %" 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,
	    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 %" TCL_Z_MODIFIER "u, compiled locals %" TCL_Z_MODIFIER "u\n",
		procPtr, procPtr->refCount, procPtr->numArgs,
		procPtr->numCompiledLocals);
    }
}
#endif /* TCL_COMPILE_DEBUG */

/*
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
#ifdef TCL_COMPILE_DEBUG
static void
ValidatePcAndStackTop(
    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
				 * stackLowerBound and stackUpperBound
				 * (inclusive). */
    int checkStack)		/* 0 if the stack depth check should be
				 * skipped. */
{
    int 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 codeEnd = (size_t)
	    (codePtr->codeStart + codePtr->numCodeBytes);
    unsigned char opCode = *pc;

    if (((size_t) pc < codeStart) || ((size_t) 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);
	Tcl_Panic("TclNRExecuteByteCode execution failure: bad opcode");
    }
    if (checkStack &&
	    ((stackTop < 0) || (stackTop > stackUpperBound))) {
	size_t 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)",
		stackTop, relativePc, stackUpperBound);
	if (cmd != NULL) {
	    Tcl_Obj *message;

	    TclNewLiteralStringObj(message, "\n executing ");
	    Tcl_IncrRefCount(message);
	    Tcl_AppendLimitedToObj(message, cmd, numChars, 100, NULL);







|





|

|
|




|




|
|
|


|
<
|


|







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
#ifdef TCL_COMPILE_DEBUG
static void
ValidatePcAndStackTop(
    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. */
    size_t stackTop,		/* Current stack top. Must be between
				 * stackLowerBound and stackUpperBound
				 * (inclusive). */
    int checkStack)		/* 0 if the stack depth check should be
				 * skipped. */
{
    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 codeEnd = (size_t)
	    (codePtr->codeStart + codePtr->numCodeBytes);
    unsigned char opCode = *pc;

    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 (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 && (stackTop > stackUpperBound)) {

	Tcl_Size numChars;
	const char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars, NULL, NULL);

	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);
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847
8848
8849
8850
    Tcl_Interp *interp,		/* Interpreter to which error information
				 * pertains. */
    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;
    int type;
    const unsigned char opcode = *pc;
    const char *description, *op = "unknown";

    if (opcode == INST_EXPON) {
	op = "**";
    } else if (opcode <= INST_LNOT) {







|







9097
9098
9099
9100
9101
9102
9103
9104
9105
9106
9107
9108
9109
9110
9111
    Tcl_Interp *interp,		/* Interpreter to which error information
				 * pertains. */
    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. */
{
    void *ptr;
    int type;
    const unsigned char opcode = *pc;
    const char *description, *op = "unknown";

    if (opcode == INST_EXPON) {
	op = "**";
    } else if (opcode <= INST_LNOT) {
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
	/* 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);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetSrcInfoForPc, GetSrcInfoForPc, TclGetSourceFromFrame --
 *







|







9122
9123
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
	/* 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, (void *)NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetSrcInfoForPc, GetSrcInfoForPc, TclGetSourceFromFrame --
 *
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
	/*
	 * 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;
	Interp *iPtr = (Interp *) *codePtr->interpHandle;
	Tcl_HashEntry *hePtr =
		Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr);

	if (!hePtr) {
	    return;
	}







|
|







9198
9199
9200
9201
9202
9203
9204
9205
9206
9207
9208
9209
9210
9211
9212
9213
	/*
	 * 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;
	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
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
				 * 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
				 * of the command containing the pc should
				 * be stored. */
{
    size_t pcOffset = (size_t)(pc - codePtr->codeStart);
    size_t 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;

    /* The pc must point within the bytecode */
    assert (pcOffset < (size_t)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.
     */








|





|



|
|


|
|
|
|
|


|







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
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. */
    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. */
    Tcl_Size *cmdIdxPtr)	/* If non-NULL, the location where the index
				 * of the command containing the pc should
				 * be stored. */
{
    Tcl_Size pcOffset = pc - codePtr->codeStart;
    Tcl_Size numCmds = codePtr->numCommands;
    unsigned char *codeDeltaNext, *codeLengthNext;
    unsigned char *srcDeltaNext, *srcLengthNext;
    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 >= 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
	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);
	prev = curr;
	while (curr <= pc) {
	    prev = curr;
	    curr += tclInstructionTable[*curr].numBytes;
	}
	*pcBeg = prev;
    }

    if (bestDist == INT_MAX) {
	return NULL;
    }

    if (lengthPtr != NULL) {
	*lengthPtr = bestSrcLength;
    }








|








|







9342
9343
9344
9345
9346
9347
9348
9349
9350
9351
9352
9353
9354
9355
9356
9357
9358
9359
9360
9361
9362
9363
9364
9365
	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 == TCL_SIZE_MAX) ? codePtr->codeStart : pc - bestDist);
	prev = curr;
	while (curr <= pc) {
	    prev = curr;
	    curr += tclInstructionTable[*curr].numBytes;
	}
	*pcBeg = prev;
    }

    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
				 * 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;
    ExceptionRange *rangePtr;
    size_t pcOffset = pc - codePtr->codeStart;
    size_t start;

    if (numRanges == 0) {
	return NULL;
    }







|







9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
				 * 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;
    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
		(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){
		return rangePtr;
	    }
	}
    }
    return NULL;
}








|







9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
		(pcOffset < (start + rangePtr->numCodeBytes))) {
	    if (rangePtr->type == CATCH_EXCEPTION_RANGE) {
		return rangePtr;
	    }
	    if (searchMode == TCL_BREAK) {
		return rangePtr;
	    }
	    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
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)) {
	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)) {
	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);
	} else {
	    s = "floating-point value too large to represent";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, NULL);
	}
    } else {
	Tcl_Obj *objPtr = Tcl_ObjPrintf(
		"unknown floating-point error, errno = %d", errno);

	Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN",
		TclGetString(objPtr), NULL);
	Tcl_SetObjResult(interp, objPtr);
    }
}

#ifdef TCL_COMPILE_STATS
/*
 *----------------------------------------------------------------------







|


|
|



|



|






|







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
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) || isnan(value)) {
	s = "domain error: argument not in valid range";
	Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", s, (void *)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, (void *)NULL);
	} else {
	    s = "floating-point value too large to represent";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW", s, (void *)NULL);
	}
    } else {
	Tcl_Obj *objPtr = Tcl_ObjPrintf(
		"unknown floating-point error, errno = %d", errno);

	Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN",
		TclGetString(objPtr), (void *)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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
EvalStatsCmd(
    ClientData unused,		/* 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;


    char *litTableStats;
    LiteralEntry *entryPtr;
    Tcl_Obj *objPtr;

#define Percent(a,b) ((a) * 100.0 / (b))

    TclNewObj(objPtr);







|













|
|
>
>







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
EvalStatsCmd(
    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;
    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
	    + (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));
    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;







|







9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
9628
9629
9630
9631
9632
	    + (statsPtr->numLiteralsCreated * sizeof(Tcl_Obj))
	    + statsPtr->totalLitStringBytes;
    totalCodeBytes = statsPtr->totalByteCodeBytes + totalLiteralBytes;

    numCurrentByteCodes =
	    statsPtr->numCompilations - statsPtr->numByteCodesFreed;
    currentHeaderBytes = numCurrentByteCodes
	    * 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
    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 (entryPtr = globalTablePtr->buckets[i];  entryPtr != NULL;
		entryPtr = entryPtr->nextPtr) {
	    if (TclHasIntRep(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) {







|


|







9727
9728
9729
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
    refCountSum = 0;
    numSharedMultX = 0;
    numSharedOnce = 0;
    objBytesIfUnshared = 0.0;
    strBytesIfUnshared = 0.0;
    strBytesSharedMultX = 0.0;
    strBytesSharedOnce = 0.0;
    for (ui = 0;  ui < globalTablePtr->numBuckets;  ui++) {
	for (entryPtr = globalTablePtr->buckets[i];  entryPtr != NULL;
		entryPtr = entryPtr->nextPtr) {
	    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
    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",
	    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);







|







9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
    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_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);
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
9598
9599
    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",
		decadeHigh, Percent(sum, statsPtr->numLiteralsCreated));
    }

    litTableStats = TclLiteralStats(globalTablePtr);
    Tcl_AppendPrintfToObj(objPtr, "\nCurrent literal table statistics:\n%s\n",
	    litTableStats);
    Tcl_Free(litTableStats);







|
|
|
|







9845
9846
9847
9848
9849
9850
9851
9852
9853
9854
9855
9856
9857
9858
9859
9860
9861
9862
    while (i-- > 0) {
	if (statsPtr->literalCount[i] > 0) {
	    maxSizeDecade = i;
	    break;
	}
    }
    sum = 0;
    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
    minSizeDecade = maxSizeDecade = 0;
    for (i = 0;  i < 31;  i++) {
	if (statsPtr->srcCount[i] > 0) {
	    minSizeDecade = i;
	    break;
	}
    }
    for (i = 31;  i >= 0;  i--) {
	if (statsPtr->srcCount[i] > 0) {
	    maxSizeDecade = i;
	    break;
	}
    }

    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",
		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--) {
	if (statsPtr->byteCodeCount[i] > 0) {
	    maxSizeDecade = i;
	    break;
	}
    }

    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",
		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--) {
	if (statsPtr->lifetimeCount[i] > 0) {
	    maxSizeDecade = i;
	    break;
	}
    }

    sum = 0;
    for (i = minSizeDecade;  i <= maxSizeDecade;  i++) {
	decadeHigh = (1 << (i+1)) - 1;
	sum += statsPtr->lifetimeCount[i];
	Tcl_AppendPrintfToObj(objPtr, "\t%12.3f\t\t%8.0f%%\n",
		decadeHigh/1000.0, Percent(sum, statsPtr->numByteCodesFreed));
    }

    /*
     * Instruction counts.
     */







|

|
|


>

|
|
|
|












|

|
|


>

|
|
|
|












|

|
|


>

|
|
|







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
    minSizeDecade = maxSizeDecade = 0;
    for (i = 0;  i < 31;  i++) {
	if (statsPtr->srcCount[i] > 0) {
	    minSizeDecade = i;
	    break;
	}
    }
    for (i = 31;  i != TCL_INDEX_NONE;  i--) {
	if (statsPtr->srcCount[i] > 0) {
	    break;		/* maxSizeDecade to consume 'i' value
				 * below... */
	}
    }
    maxSizeDecade = i;
    sum = 0;
    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 != TCL_INDEX_NONE;  i--) {
	if (statsPtr->byteCodeCount[i] > 0) {
	    break;		/* maxSizeDecade to consume 'i' value
				 * below... */
	}
    }
    maxSizeDecade = i;
    sum = 0;
    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 != TCL_INDEX_NONE;  i--) {
	if (statsPtr->lifetimeCount[i] > 0) {
	    break;		/* maxSizeDecade to consume 'i' value
				 * below... */
	}
    }
    maxSizeDecade = i;
    sum = 0;
    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
/*
 * tclFCmd.c
 *
 *	This file implements the generic portion of file manipulation
 *	subcommands of the "file" command.
 *
 * Copyright (c) 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"






|







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 © 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
 *	See the user documentation.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileRenameCmd(
    TCL_UNUSED(ClientData),
    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);
}







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 *	See the user documentation.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileRenameCmd(
    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
 *	See the user documentation.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileCopyCmd(
    TCL_UNUSED(ClientData),
    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);
}







|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
 *	See the user documentation.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileCopyCmd(
    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
    Tcl_Obj *const objv[],	/* Argument strings passed to Tcl_FileCmd. */
    int copyFlag)		/* If non-zero, copy source(s). Otherwise,
				 * rename them. */
{
    int i, result, force;
    Tcl_StatBuf statBuf;
    Tcl_Obj *target;


    i = FileForceOption(interp, objc - 1, objv + 1, &force);
    if (i < 0) {
	return TCL_ERROR;
    }
    i++;
    if ((objc - i) < 2) {







>







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
     * 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;
    }







    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.







>
>
>
>
>
>







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
TclFileMakeDirsCmd(
    TCL_UNUSED(ClientData),
    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;

    Tcl_Obj *split = NULL;
    Tcl_Obj *target = NULL;
    Tcl_StatBuf statBuf;


    result = TCL_OK;
    for (i = 1; i < objc; i++) {
	if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
	    result = TCL_ERROR;
	    break;
	}








	split = Tcl_FSSplitPath(objv[i], &pobjc);
	Tcl_IncrRefCount(split);
	if (pobjc == 0) {
	    errno = ENOENT;
	    errfile = objv[i];
	    break;







|





|
>



>







>
>
>
>
>
>
>







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
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(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;
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
TclFileDeleteCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Used for error reporting */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* Argument strings passed to Tcl_FileCmd. */
{
    int i, force, result;
    Tcl_Obj *errfile;
    Tcl_Obj *errorBuffer = NULL;


    i = FileForceOption(interp, objc - 1, objv + 1, &force);
    if (i < 0) {
	return TCL_ERROR;
    }

    errfile = NULL;
    result = TCL_OK;

    for (i++ ; i < objc; i++) {
	Tcl_StatBuf statBuf;

	errfile = objv[i];
	if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
	    result = TCL_ERROR;
	    goto done;
	}








	/*
	 * Call lstat() to get info so can delete symbolic link itself.
	 */

	if (Tcl_FSLstat(objv[i], &statBuf) != 0) {
	    result = TCL_ERROR;







|







>

















>
>
>
>
>
>
>







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(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
	    result = TCL_ERROR;
	    break;
	}
    }
    if (result != TCL_OK) {
	if (errfile == NULL) {
	    /*
	     * We try to accomodate 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(







|







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 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
				 * exists. */
{
    int result;
    Tcl_Obj *errfile, *errorBuffer;
    Tcl_Obj *actualSource=NULL;	/* If source is a link, then this is the real
				 * file/directory. */
    Tcl_StatBuf sourceStatBuf, targetStatBuf;


    if (Tcl_FSConvertToPathType(interp, source) != TCL_OK) {
	return TCL_ERROR;
    }






    if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
	return TCL_ERROR;
    }







    errfile = NULL;
    errorBuffer = NULL;
    result = TCL_ERROR;

    /*
     * We want to copy/rename links and not the files they point to, so we use







>




>
>
>
>
>
>



>
>
>
>
>
>







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
900
901
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static Tcl_Obj *
FileBasename(
    Tcl_Interp *interp,		/* Interp, for error return. */
    Tcl_Obj *pathPtr)		/* Path whose basename to extract. */
{
    int 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);
	    if ((objc == 1) &&
		    (Tcl_FSGetPathType(resultPtr) != TCL_PATH_RELATIVE)) {







|


|







<
<
<
<
<
<
<
<
<
|
|







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
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static Tcl_Obj *
FileBasename(
    TCL_UNUSED(Tcl_Interp *),	/* Interp, for error return. */
    Tcl_Obj *pathPtr)		/* Path whose basename to extract. */
{
    Tcl_Size objc;
    Tcl_Obj *splitPtr;
    Tcl_Obj *resultPtr = NULL;

    splitPtr = Tcl_FSSplitPath(pathPtr, &objc);
    Tcl_IncrRefCount(splitPtr);

    if (objc != 0) {









        /*
         * 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);
	    if ((objc == 1) &&
		    (Tcl_FSGetPathType(resultPtr) != TCL_PATH_RELATIVE)) {
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
 *	May set file attributes for the file name.
 *
 *----------------------------------------------------------------------
 */

int
TclFileAttrsCmd(
    TCL_UNUSED(ClientData),
    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_Obj *filePtr;


    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?-option value ...?");
	return TCL_ERROR;
    }

    filePtr = objv[1];
    if (Tcl_FSConvertToPathType(interp, filePtr) != TCL_OK) {
	return TCL_ERROR;
    }







    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_Obj *objPtr;

	if (objStrings == NULL) {
	    if (Tcl_GetErrno() != 0) {
		/*
		 * There was an error, probably that the filePtr is not
		 * accepted by any filesystem







|








|

>










>
>
>
>
>
>












|







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(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;
    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) {
	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

	Tcl_IncrRefCount(objStrings);

	/*
	 * Use objStrings as a list object.
	 */

	if (Tcl_ListObjLength(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);







|







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 (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
	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);
	    goto end;
	}

	if (Tcl_GetIndexFromObj(interp, objv[0], attributeStrings,
		"option", TCL_INDEX_TEMP_TABLE, &index) != TCL_OK) {
	    goto end;
	}







|







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", (void *)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

	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);
	    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);
		goto end;
	    }
	    if (Tcl_FSFileAttrsSet(interp, index, filePtr,
		    objv[i + 1]) != TCL_OK) {
		goto end;
	    }
	}







|












|







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", (void *)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", (void *)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
 *	May create a new link.
 *
 *----------------------------------------------------------------------
 */

int
TclFileLinkCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *contents;
    int index;


    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-linktype? linkname ?target?");
	return TCL_ERROR;
    }

    /*







|






>







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(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
	    }
	} else {
	    linkAction = TCL_CREATE_SYMBOLIC_LINK | TCL_CREATE_HARD_LINK;
	}
	if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
	    return TCL_ERROR;
	}







	/*
	 * Create link from source to target.
	 */

	contents = Tcl_FSLink(objv[index], objv[index+1], linkAction);
	if (contents == NULL) {
	    /*
	     * We handle three common error cases specially, and for all other
	     * 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);







>
>
>
>
>
>









|







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.
	     */

	    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
	    }
	    return TCL_ERROR;
	}
    } else {
	if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
	    return TCL_ERROR;
	}







	/*
	 * Read link
	 */

	contents = Tcl_FSLink(objv[index], NULL, 0);
	if (contents == NULL) {







>
>
>
>
>
>







1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
	    }
	    return TCL_ERROR;
	}
    } else {
	if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[index]),
		TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	Tcl_DStringFree(&ds);

	/*
	 * Read link
	 */

	contents = Tcl_FSLink(objv[index], NULL, 0);
	if (contents == NULL) {
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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclFileReadLinkCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *contents;


    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    }

    if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
	return TCL_ERROR;
    }







    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)));







|





>









>
>
>
>
>
>







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(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
 *	to a variable, so reentrancy is a potential issue.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileTemporaryCmd(
    TCL_UNUSED(ClientData),
    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. */







|







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(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
    }

    if (objc > 1) {
	nameVarObj = objv[1];
	TclNewObj(nameObj);
    }
    if (objc > 2) {
	size_t length;
	Tcl_Obj *templateObj = objv[2];
	const char *string = TclGetStringFromObj(templateObj, &length);

	/*
	 * Treat an empty string as if it wasn't there.
	 */








|







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) {
	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
 *	Creates a temporary directory.
 *
 *---------------------------------------------------------------------------
 */

int
TclFileTempDirCmd(
    TCL_UNUSED(ClientData),
    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_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.
	 */







|

















|







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(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) {
	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
		"can't create temporary directory: %s",
		Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, dirNameObj);
    return TCL_OK;
}

/*












































































 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






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
/*
 * 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.
 *
 * 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);









/*
 * 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.
 */







|
|




















<
<









>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


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 © 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 *	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
 *
 *	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.
 *
 * 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] == '\\')) {
	extended = 1;
	path = path + 4;
	if (path[0] == 'U' && path[1] == 'N' && path[2] == 'C'
	    && (path[3] == '/' || path[3] == '\\')) {
	    extended = 2;
	    path = path + 4;
	}
    }

    if (path[0] == '/' || path[0] == '\\') {
	/*







|

















|
|
|
|



|







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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 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] == '\\')) {
	extended = 1;
	path = path + 4;
	if (path[0] == 'U' && path[1] == 'N' && path[2] == 'C'
		&& (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
		    && 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') {
		    abs = 5;
		}

	    } else if ((path[2] == 'n' || path[2] == 'N') && path[3] == '\0') {
		/*
		 * Have match for 'con'.
		 */







|







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') {
		    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
	    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') {
		    abs = 5;
		}
	    }

	} else if ((path[0] == 'p' || path[0] == 'P')
		&& (path[1] == 'r' || path[1] == 'R')
		&& (path[2] == 'n' || path[2] == 'N')







|







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') {
		    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
 *	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_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;

	    /*
	     * Paths that begin with / are absolute.
	     */

	    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;
		    }
#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.
		     */

		    *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;
	}
	}
    }
    return type;
}

/*
 *---------------------------------------------------------------------------
 *







<
<
<
<
<
<













|
|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|

|
|
|

|
|
<
|
|
|
|
|
|
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
<







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.
 *






 * 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 */
    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);















    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX: {
        const char *origPath = path;

        /*
         * Paths that begin with / are absolute.
         */

        if (path[0] == '/') {
            ++path;

            /*
             * Check for "//" network path prefix
             */
            if ((*path == '/') && path[1] && (path[1] != '/')) {
                path += 2;
                while (*path && *path != '/') {
                    ++path;
                }






            }






            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;

        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
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclpNativeSplitPath(
    Tcl_Obj *pathPtr,		/* Path to split. */
    int *lenPtr)		/* int to store number of path elements. */
{
    Tcl_Obj *resultPtr = NULL;	/* Needed only to prevent gcc warnings. */

    /*
     * Perform platform specific splitting.
     */








|







461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclpNativeSplitPath(
    Tcl_Obj *pathPtr,		/* Path to split. */
    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
    }

    /*
     * Compute the number of elements in the result.
     */

    if (lenPtr != NULL) {
	Tcl_ListObjLength(NULL, resultPtr, lenPtr);
    }
    return resultPtr;
}

/*
 *----------------------------------------------------------------------
 *







|







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) {
	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
 *
 * Side effects:
 *	Allocates memory.
 *
 *----------------------------------------------------------------------
 */


void
Tcl_SplitPath(
    const char *path,		/* Pointer to string containing a path. */
    int *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;
    char *p;
    const char *str;

    /*
     * Perform the splitting, using objectified, vfs-aware code.
     */








>



|






<
|







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. */
    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;

    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
     * Now set up the argv pointers.
     */

    p = (char *) &(*argvPtr)[(*argcPtr) + 1];

    for (i = 0; i < *argcPtr; i++) {
	(*argvPtr)[i] = p;
	for (; *(p++)!='\0'; );
    }
    (*argvPtr)[i] = NULL;

    /*
     * Free the result ptr given to us by Tcl_FSSplitPath
     */








|







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;
	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
713
     * 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
     * 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);
	    }
	    Tcl_ListObjAppendElement(NULL, result, nextElt);
	}
	if (*path++ == '\0') {
	    break;
	}
    }
    return result;
}







<








<
<
<
<
<
<
|
<
<
<
<
<
<








|
<










<
<
<
<
|
<
|







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
     * Deal with the root directory as a special case.
     */

    TclNewObj(result);
    if (*path == '/') {
	Tcl_Obj *rootElt;
	++path;

	/*
	 * Check for "//" network path prefix
	 */
	if ((*path == '/') && path[1] && (path[1] != '/')) {
	    path += 2;
	    while (*path && *path != '/') {
		++path;
	    }






	}






	rootElt = Tcl_NewStringObj(origPath, path - origPath);
	Tcl_ListObjAppendElement(NULL, result, rootElt);
	while (*path == '/') {
	    ++path;
	}
    }

    /*
     * Split on slashes.

     */

    for (;;) {
	elementStart = path;
	while ((*path != '\0') && (*path != '/')) {
	    path++;
	}
	length = path - elementStart;
	if (length > 0) {
	    Tcl_Obj *nextElt;




            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
    p = ExtractWinRoot(path, &buf, 0, &type);

    /*
     * Terminate the root portion, if we matched something.
     */

    if (p != path) {
	Tcl_ListObjAppendElement(NULL, result, TclDStringToObj(&buf));
    }
    Tcl_DStringFree(&buf);

    /*
     * Split on slashes. Embedded elements that start with tilde or a drive
     * 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] == ':'))) {
		TclNewLiteralStringObj(nextElt, "./");
		Tcl_AppendToObj(nextElt, elementStart, length);
	    } else {
		nextElt = Tcl_NewStringObj(elementStart, length);
	    }
	    Tcl_ListObjAppendElement(NULL, result, nextElt);
	}







|




|
<
<










|
|
|







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, Tcl_DStringToObj(&buf));
    }
    Tcl_DStringFree(&buf);

    /*
     * Split on slashes.


     */

    do {
	elementStart = p;
	while ((*p != '\0') && (*p != '/') && (*p != '\\')) {
	    p++;
	}
	length = p - elementStart;
	if (length > 0) {
	    Tcl_Obj *nextElt;
	    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
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_FSJoinToPath(
    Tcl_Obj *pathPtr,		/* Valid path or NULL. */
    int 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_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;







|















|







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. */
    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 {
	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

void
TclpNativeJoinPath(
    Tcl_Obj *prefix,
    const char *joining)
{
    int needsSep;
    size_t length;
    char *dest;
    const char *p;
    const char *start;

    start = TclGetStringFromObj(prefix, &length);

    /*
     * Remove the ./ from tilde prefixed elements, and 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] == ':')))) {
	    p += 2;
	}
    }
    if (*p == '\0') {
	return;
    }








|







|






|
|
|







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;
    Tcl_Size length;
    char *dest;
    const char *p;
    const char *start;

    start = TclGetStringFromObj(prefix, &length);

    /*
     * 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] == '/') &&
		(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
	}
	needsSep = 0;

	/*
	 * Append the element, eliminating duplicate and trailing slashes.
	 */

	Tcl_SetObjLength(prefix, length + (int) strlen(p));

	dest = TclGetString(prefix) + length;
	for (; *p != '\0'; p++) {
	    if (*p == '/') {
		while (p[1] == '/') {
		    p++;
		}







|







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 + 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
 *	Modifies the Tcl_DString.
 *
 *----------------------------------------------------------------------
 */

char *
Tcl_JoinPath(
    int argc,
    const char *const *argv,
    Tcl_DString *resultPtr)	/* Pointer to previously initialized DString */
{
    int i;
    size_t len;
    Tcl_Obj *listObj;
    Tcl_Obj *resultObj;
    const char *resultStr;

    /*
     * Build the list of paths.
     */







|



<
|







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(
    Tcl_Size argc,
    const char *const *argv,
    Tcl_DString *resultPtr)	/* Pointer to previously initialized DString */
{

    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

/*
 *---------------------------------------------------------------------------
 *
 * 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
 *	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
 *	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. */
{
    Tcl_Obj *path = Tcl_NewStringObj(name, -1);
    Tcl_Obj *transPtr;

    Tcl_IncrRefCount(path);
    transPtr = Tcl_FSGetTranslatedPath(interp, path);
    if (transPtr == NULL) {







|
<
<


|
>
|
|


<
<
<
















|







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.


 *
 * Results:
 *	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.



 *
 * 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. */
{
    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

    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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index, i, globFlags, length, join, dir, result;

    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
    };
    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) {
	    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) {
	case GLOB_NOCOMPLAIN:			/* -nocomplain */
	    globFlags |= TCL_GLOBMODE_NO_COMPLAIN;




	    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);
		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);
		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);
		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);
		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);
		return TCL_ERROR;
	    }
	    typePtr = objv[i+1];
	    if (Tcl_ListObjLength(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);
	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;
	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) {
		break;
	    }
	}

	if (last == first + pathlength) {
	    /*
	     * It's really a directory.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















|




|
>












|








|
|



















|

<
>
>
>
>





|









|

















|









|










|



|
















|














|









|







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;
}

/*
 *----------------------------------------------------------------------
 *



























































 * 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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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) {
	    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 (index) {
	case GLOB_NOCOMPLAIN:			/* -nocomplain */

	    /*
	     * 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", (void *)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", (void *)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", (void *)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", (void *)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", (void *)NULL);
		return TCL_ERROR;
	    }
	    typePtr = objv[i+1];
	    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", (void *)NULL);
	return TCL_ERROR;
    }

    separators = NULL;
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX:
	separators = "/";
	break;
    case TCL_PLATFORM_WINDOWS:
	separators = "/\\:";
	break;
    }

    if (dir == PATH_GENERAL) {
	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) {
		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
		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.

		 */

		if (strpbrk(TclGetString(pathOrDir), "\\/") == NULL) {

		    Tcl_AppendToObj(pathOrDir, last-1, 1);


		}
	    }

	    /*
	     * Need to quote 'prefix'.
	     */








|
>


|
>

>
>







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. Similar treatment
		 * for the zipfs volume.
		 */

		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
    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) {
	    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;
	    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) {







|
|








|
|







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.
	 */

	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) {
	    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
		    goto badMacTypesArg;
		}
		globTypes->macType = look;
		Tcl_IncrRefCount(look);

	    } else {
		Tcl_Obj *item;
		int llen;

		if ((Tcl_ListObjLength(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) {







|

|







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;
		Tcl_Size llen;

		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
		 * 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);
		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);
		join = 0;
		goto endOfGlob;
	    }
	}
    }

  skipTypes:







|









|







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", (void *)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", (void *)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
		    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);
    }







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1524
1525
1526
1527
1528
1529
1530



































1531
1532
1533
1534
1535
1536
1537
		    globTypes) != TCL_OK) {
		result = TCL_ERROR;
		goto endOfGlob;
	    }
	}
    }




































  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
}

/*
 *----------------------------------------------------------------------
 *
 * TclGlob --
 *
 *	Sets the separator string based on the platform, performs tilde
 *	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







|
<







1548
1549
1550
1551
1552
1553
1554
1555

1556
1557
1558
1559
1560
1561
1562
}

/*
 *----------------------------------------------------------------------
 *
 * TclGlob --
 *
 *	Sets the separator string based on the platform	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
 *
 * Side effects:
 *	The 'pattern' is written to.
 *
 *----------------------------------------------------------------------
 */

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;
    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) {
	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);
	    globFlags |= TCL_GLOBMODE_DIR;
	    if (c != '\0') {
		tail++;
	    }
	    Tcl_DStringFree(&buffer);
	} else {
	    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.
     *







|












<
|













|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
|
<
<
<
<
<







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.
 *
 *----------------------------------------------------------------------
 */

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;

    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) {








































	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
		}
		p++;
	    }
	    tail = p;
	    Tcl_IncrRefCount(pathPrefix);
	} else if (pathPrefix == NULL && (tail[0] == '/'
		|| (tail[0] == '\\' && tail[1] == '\\'))) {
	    int 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: {
		/*







|







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] == '\\'))) {
	    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

    /*
     * 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_Obj *driveName;
	if (TclFSNonnativePathType(tail, (int) 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.
     */

    savedResultObj = Tcl_GetObjResult(interp);
    Tcl_IncrRefCount(savedResultObj);
    Tcl_ResetResult(interp);
    TclNewObj(filenamesObj);
    Tcl_IncrRefCount(filenamesObj);







|

|










|







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) {
	Tcl_Size driveNameLen;
	Tcl_Obj *driveName;
	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 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
     * 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_Obj **objv;
	size_t prefixLen;
	const char *pre;

	/*
	 * If this length has never been set, set it here.
	 */

	if (pathPrefix == NULL) {







|

|







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) {
	Tcl_Size objc, i;
	Tcl_Obj **objv;
	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

	    if ((tclPlatform != TCL_PLATFORM_WINDOWS) || (prefixLen != 2)
		    || (pre[1] != ':')) {
		prefixLen++;
	    }
	}

	Tcl_ListObjGetElements(NULL, filenamesObj, &objc, &objv);
	for (i = 0; i< objc; i++) {
	    size_t 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, ".");







|

|







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++;
	    }
	}

	TclListObjGetElements(NULL, filenamesObj, &objc, &objv);
	for (i = 0; i< objc; i++) {
	    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
    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 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.
     */








|









<



















<







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;
    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.
     */


    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;
	}

    }

    /*
     * 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

		closeBrace = p;
		break;
	    }
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "unmatched open-brace in file name", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "GLOB", "BALANCE",
		    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);
	    return TCL_ERROR;
	}
    }

    /*
     * Substitute the alternate patterns from the braces and recurse.
     */







|






|







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",
		    (void *)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",
		    (void *)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
	*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_Obj **subdirv;

	    result = Tcl_ListObjGetElements(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_DecrRefCount(subdirv[i]);
		    subdirv[i] = copy;
		    Tcl_ListObjLength(NULL, matchesObj, &end);
		    while (repair < end) {
			const char *bytes;
			size_t 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;
		}
	    }
	}
	TclDecrRefCount(subdirsPtr);
	return result;
    }

    /*
     * We reach here with no pattern char in current section
     */

    if (*p == '\0') {
	size_t 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







|


|




<
<
<
<
<
<
<



|



|


|









|












|







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) {
	    Tcl_Size i, subdirc, repair = -1;
	    Tcl_Obj **subdirv;

	    result = TclListObjGetElements(interp, subdirsPtr,
		    &subdirc, &subdirv);
	    for (i=0; result==TCL_OK && i<subdirc; i++) {
		Tcl_Obj *copy = NULL;








		result = DoGlob(interp, matchesObj, separators, subdirv[i],
			1, p+1, types);
		if (copy) {
		    Tcl_Size end;

		    Tcl_DecrRefCount(subdirv[i]);
		    subdirv[i] = copy;
		    TclListObjLength(NULL, matchesObj, &end);
		    while (repair < end) {
			const char *bytes;
			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 = TCL_INDEX_NONE;
		}
	    }
	}
	TclDecrRefCount(subdirsPtr);
	return result;
    }

    /*
     * We reach here with no pattern char in current section
     */

    if (*p == '\0') {
	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
	}

	/*
	 * Common for all platforms.
	 */

	if (pathPtr == NULL) {
	    joinedPtr = TclDStringToObj(&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;
		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),







|










|







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 = 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.
		 */

		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
	     * 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;
	    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);
		}
	    }







|







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.
	     */

	    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

/*
 *---------------------------------------------------------------------------
 *
 * 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]
 *
 * Results:
 *	The value from the field being retrieved.
 *
 * Side effects:
 *	None.
 *







|
|







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'
 *	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
int
Tcl_GetDeviceTypeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (int) statPtr->st_rdev;
}

Tcl_WideInt
Tcl_GetAccessTimeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (Tcl_WideInt) statPtr->st_atime;
}

Tcl_WideInt
Tcl_GetModificationTimeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (Tcl_WideInt) statPtr->st_mtime;
}

Tcl_WideInt
Tcl_GetChangeTimeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (Tcl_WideInt) statPtr->st_ctime;
}

Tcl_WideUInt
Tcl_GetSizeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (Tcl_WideUInt) statPtr->st_size;
}

Tcl_WideUInt
Tcl_GetBlocksFromStat(
    const Tcl_StatBuf *statPtr)
{
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    return (Tcl_WideUInt) statPtr->st_blocks;
#else
    unsigned blksize = Tcl_GetBlockSizeFromStat(statPtr);

    return ((Tcl_WideUInt) statPtr->st_size + blksize - 1) / blksize;
#endif
}

#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
unsigned
Tcl_GetBlockSizeFromStat(
    const Tcl_StatBuf *statPtr)







|



|


|



|


|



|


|



|


|




|



|







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;
}

long long
Tcl_GetAccessTimeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (long long) statPtr->st_atime;
}

long long
Tcl_GetModificationTimeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (long long) statPtr->st_mtime;
}

long long
Tcl_GetChangeTimeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (long long) statPtr->st_ctime;
}

unsigned long long
Tcl_GetSizeFromStat(
    const Tcl_StatBuf *statPtr)
{
    return (unsigned long long) statPtr->st_size;
}

unsigned long long
Tcl_GetBlocksFromStat(
    const Tcl_StatBuf *statPtr)
{
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
    return (unsigned long long) statPtr->st_blocks;
#else
    unsigned blksize = Tcl_GetBlockSizeFromStat(statPtr);

    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
/*
 * tclFileSystem.h --
 *
 *	This file contains the common defintions 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.
 */



|







1
2
3
4
5
6
7
8
9
10
11
/*
 * tclFileSystem.h --
 *
 *	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
/*
 * 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);
MODULE_SCOPE Tcl_PathType TclFSNonnativePathType(const char *pathPtr,
			    int pathLen, const Tcl_Filesystem **filesystemPtrPtr,
			    int *driveNameLengthPtr, Tcl_Obj **driveNameRef);
MODULE_SCOPE Tcl_PathType TclGetPathType(Tcl_Obj *pathPtr,
			    const Tcl_Filesystem **filesystemPtrPtr,
			    int *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;







|

|
|


|







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,
			    Tcl_Size *driveNameLengthPtr);
MODULE_SCOPE Tcl_PathType TclFSNonnativePathType(const char *pathPtr,
			    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,
			    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
/*
 * 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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"








|
|







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 © 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
    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);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetDouble --







|







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");
    }
    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
    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);
    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
 *	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.
 *
 *----------------------------------------------------------------------
 */



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 *boolPtr)		/* Place to store converted result, which will
				 * be 0 or 1. */
{
    Tcl_Obj obj;
    int code;




    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;
    }
    return code;
}













/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|












|










>
>

|



>
|





>
>
>










|



>
>
>
>
>
>
>
>
>
>
>
>








93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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");
    }
    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 *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_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,
    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) {
	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
/*
 * 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.

 *
 * 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.

 *
 * 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 {
    MERam, MERpm, MER24
} MERIDIAN;


/*
 * yyparse will accept a 'struct DateInfo' as its parameter; that's where the
 * parsed fields will be returned.
 */

typedef struct DateInfo {

    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))






/*
 * An entry in the lexical lookup table.
 */

typedef struct _TABLE {
    const char *name;
    int type;
    time_t value;
} TABLE;

/*
 * Daylight-savings mode: on, off, or not yet known.
 */

typedef enum _DSTMODE {
    DSTon, DSToff, DSTmaybe
} DSTMODE;

%}

%union {
    time_t Number;
    enum _MERIDIAN Meridian;
}

%{

/*
 * Prototypes of internal functions.
 */

static int		LookupWord(YYSTYPE* yylvalPtr, char *buff);
 static void		TclDateerror(YYLTYPE* location,
				     DateInfo* info, const char *s);
 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	tEPOCH
%token	tDST
%token	tISOBASE


%token	tDAY_UNIT
%token	tNEXT


%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>	tZONE


%type	<Number>	tISOBASE


%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

	;

item	: time {
	    yyHaveTime++;
	}
	| zone {
	    yyHaveZone++;
	}
	| date {
	    yyHaveDate++;
	}
	| ordMonth {
	    yyHaveOrdinalMonth++;
	}
	| day {
	    yyHaveDay++;
	}
	| relspec {
	    yyHaveRel++;
	}
	| iso {
	    yyHaveTime++;
	    yyHaveDate++;
	}
	| trek {

	    yyHaveTime++;
	    yyHaveDate++;
	    yyHaveRel++;
	}
	| number
	;












time	: tUNUMBER tMERIDIAN {
	    yyHour = $1;
	    yyMinutes = 0;
	    yySeconds = 0;
	    yyMeridian = $2;
	}
	| tUNUMBER ':' tUNUMBER o_merid {
	    yyHour = $1;
	    yyMinutes = $3;
	    yySeconds = 0;
	    yyMeridian = $4;
	}
	| 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;
	}








	| sign tUNUMBER {
	    yyTimezone = -$1*($2 % 100 + ($2 / 100) * 60);
	    yyDSTmode = DSToff;
	}
	;





day	: tDAY {
	    yyDayOrdinal = 1;
	    yyDayNumber = $1;
	}
	| tDAY ',' {
	    yyDayOrdinal = 1;
	    yyDayNumber = $1;
	}
	| tUNUMBER tDAY {
	    yyDayOrdinal = $1;
	    yyDayNumber = $2;




	}
	| sign tUNUMBER tDAY {
	    yyDayOrdinal = $1 * $2;
	    yyDayNumber = $3;
	}
	| tNEXT tDAY {
	    yyDayOrdinal = 2;
	    yyDayNumber = $2;
	}
	;







date	: tUNUMBER '/' tUNUMBER {
	    yyMonth = $1;
	    yyDay = $3;
	}
	| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
	    yyMonth = $1;
	    yyDay = $3;
	    yyYear = $5;
	}
	| tISOBASE {
	    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 {
	    yyMonth = $1;
	    yyDay = $2;
	    yyYear = $4;
	}
	| tUNUMBER tMONTH {
	    yyMonth = $2;
	    yyDay = $1;









|
|
>


















|
|
>
















<
<
<
|
|
<
<
>






<
|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<











|
>
|
|
>
>
>
>
>





|


|













|










|

|

<
<













|
|
|
>


|
>
>


>







|
|

>
>
|
>
>












>



|


|


|


|


|


|


|
<


>
|
<
<

|


>
>
>
>
>
>
>
>
>
>
>






|
<
<
<
|
<
<
<
<
<
<





<




<






>
>
>
>
>
>
>
>
|




>
>
>
>



|

|

|



|
>
>
>
>



|



|



>
>
>
>
>
>









|
<
<
<
<





<
<
<
<
<




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49



50
51


52
53
54
55
56
57
58

59


60


































61
62
63

























64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198
199


200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221



222






223
224
225
226
227

228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
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 © 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 © 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 */




#if 0
#define YYDEBUG 1


#endif

/*
 * yyparse will accept a 'struct DateInfo' as its parameter; that's where the
 * parsed fields will be returned.
 */


#include "tclDate.h"





































#define YYMALLOC	Tcl_Alloc
#define YYFREE(x)	(Tcl_Free((void*) (x)))


























#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)		((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 {
    const char *name;
    int type;
    int value;
} TABLE;

/*
 * Daylight-savings mode: on, off, or not yet known.
 */

typedef enum _DSTMODE {
    DSTon, DSToff, DSTmaybe
} DSTMODE;

%}

%union {
    Tcl_WideInt Number;
    enum _MERIDIAN Meridian;
}

%{

/*
 * Prototypes of internal functions.
 */

static int		LookupWord(YYSTYPE* yylvalPtr, char *buff);
static void		TclDateerror(YYLTYPE* location,
				     DateInfo* info, const char *s);
static int		TclDatelex(YYSTYPE* yylvalPtr, YYLTYPE* location,
				   DateInfo* info);


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	tUNUMBER
%token	tZONE
%token	tZONEwO4
%token	tZONEwO2
%token	tEPOCH
%token	tDST
%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>	tUNUMBER
%type	<Number>	INTNUM
%type	<Number>	tZONE
%type	<Number>	tZONEwO4
%type	<Number>	tZONEwO2
%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 {
	    yyIncrFlags(CLF_TIME);
	}
	| zone {
	    yyIncrFlags(CLF_ZONE);
	}
	| date {
	    yyIncrFlags(CLF_HAVEDATE);
	}
	| ordMonth {
	    yyIncrFlags(CLF_ORDINALMONTH);
	}
	| day {
	    yyIncrFlags(CLF_DAYOFWEEK);
	}
	| relspec {
	    info->flags |= CLF_RELCONV;
	}
	| iso {
	    yyIncrFlags(CLF_TIME|CLF_HAVEDATE);

	}
	| trek {
	    yyIncrFlags(CLF_TIME|CLF_HAVEDATE);
	    info->flags |= CLF_RELCONV;


	}
	| 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;
	}
	| iextime o_merid {



	    yyMeridian = $2;






	}
	;

zone	: tZONE tDST {
	    yyTimezone = $1;

	    yyDSTmode = DSTon;
	}
	| tZONE {
	    yyTimezone = $1;

	    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 INTNUM { /* +0100, -0100 */
	    yyTimezone = -$1*($2 % 100 + ($2 / 100) * 60);
	    yyDSTmode = DSToff;
	}
	;

comma	: ','
	| ',' SP
	;

day	: tDAY {
	    yyDayOrdinal = 1;
	    yyDayOfWeek = $1;
	}
	| tDAY comma {
	    yyDayOrdinal = 1;
	    yyDayOfWeek = $1;
	}
	| tUNUMBER tDAY {
	    yyDayOrdinal = $1;
	    yyDayOfWeek = $2;
	}
	| sign SP tUNUMBER tDAY {
	    yyDayOrdinal = $1 * $3;
	    yyDayOfWeek = $4;
	}
	| sign tUNUMBER tDAY {
	    yyDayOrdinal = $1 * $2;
	    yyDayOfWeek = $3;
	}
	| tNEXT tDAY {
	    yyDayOrdinal = 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;
	}
	| isodate




	| tUNUMBER '-' tMONTH '-' tUNUMBER {
	    yyDay = $1;
	    yyMonth = $3;
	    yyYear = $5;
	}





	| tMONTH tUNUMBER {
	    yyMonth = $1;
	    yyDay = $2;
	}
	| 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
	    yyMonth = $2;
	    yyDay = $1;
	    yyYear = $3;
	}
	;

ordMonth: tNEXT tMONTH {
	    yyMonthOrdinal = 1;
	    yyMonth = $2;
	}
	| tNEXT tUNUMBER tMONTH {
	    yyMonthOrdinal = $2;
	    yyMonth = $3;
	}
	;

iso	: tUNUMBER '-' tUNUMBER '-' tUNUMBER tZONE
		tUNUMBER ':' tUNUMBER ':' tUNUMBER {

	    if ($6 != HOUR( 7) + HOUR(100)) YYABORT;
	    yyYear = $1;
	    yyMonth = $3;
	    yyDay = $5;
	    yyHour = $7;
	    yyMinutes = $9;
	    yySeconds = $11;
	}
	| tISOBASE tZONE tISOBASE {
	    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;
	}


	| tISOBASE tZONE tUNUMBER ':' tUNUMBER ':' tUNUMBER {
	    if ($2 != HOUR( 7) + HOUR(100)) YYABORT;
	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;
	    yyHour = $3;
	    yyMinutes = $5;
	    yySeconds = $7;
	}



	| tISOBASE tISOBASE {
	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;
	    yyHour = $2 / 10000;
	    yyMinutes = ($2 % 10000)/100;
	    yySeconds = $2 % 100;
	}









	;

trek	: tSTARDATE tUNUMBER '.' 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;
	}
	;

relspec : relunits tAGO {
	    yyRelSeconds *= -1;
	    yyRelMonth *= -1;
	    yyRelDay *= -1;
	}
	| relunits
	;

relunits : sign tUNUMBER unit {



	    *yyRelPointer += $1 * $2 * $3;
	}
	| tUNUMBER unit {
	    *yyRelPointer += $1 * $2;
	}
	| tNEXT unit {
	    *yyRelPointer += $2;
	}
	| tNEXT tUNUMBER unit {
	    *yyRelPointer += $2 * $3;
	}
	| unit {
	    *yyRelPointer += $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
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 {
	    yyMonthOrdinalIncr = 1;
	    yyMonthOrdinal = $2;
	}
	| tNEXT tUNUMBER tMONTH {
	    yyMonthOrdinalIncr = $2;
	    yyMonthOrdinal = $3;
	}
	;

isosep	: 'T'|SP

	;
isodate	: tISOBAS8 { /* YYYYMMDD */
	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;



	}
	| tISOBAS6 { /* YYMMDD */

	    yyYear = $1 / 10000;
	    yyMonth = ($1 % 10000)/100;
	    yyDay = $1 % 100;



	}
	| iexdate
	;
isotime	: tISOBAS6 {




	    yyHour = $1 / 10000;
	    yyMinutes = ($1 % 10000)/100;
	    yySeconds = $1 % 100;
	}
	| iextime
	;
iso	: isodate isosep isotime
	| 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 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 * (144LL * 60LL);
	}
	;

relspec : relunits tAGO {
	    yyRelSeconds *= -1;
	    yyRelMonth *= -1;
	    yyRelDay *= -1;
	}
	| relunits
	;

relunits : sign SP INTNUM unit {
	    *yyRelPointer += $1 * $3 * $4;
	}
	| sign INTNUM unit {
	    *yyRelPointer += $1 * $2 * $3;
	}
	| INTNUM unit {
	    *yyRelPointer += $1 * $2;
	}
	| tNEXT unit {
	    *yyRelPointer += $2;
	}
	| 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
	}
	| tMONTH_UNIT {
	    $$ = $1;
	    yyRelPointer = &yyRelMonth;
	}
	;

number	: tUNUMBER {









	    if (yyHaveTime && yyHaveDate && !yyHaveRel) {


		yyYear = $1;
	    } else {
		yyHaveTime++;
		if (yyDigitCount <= 2) {
		    yyHour = $1;
		    yyMinutes = 0;
		} else {
		    yyHour = $1 / 100;
		    yyMinutes = $1 % 100;
		}







|
>
>
>
>
>
>
>
>
>
|
>
>


|







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;
	}
	;

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 {
		yyIncrFlags(CLF_TIME);
		if (yyDigitCount <= 2) {
		    yyHour = $1;
		    yyMinutes = 0;
		} else {
		    yyHour = $1 / 100;
		    yyMinutes = $1 % 100;
		}
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
    { "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 }
};

/*







<
<
<
<
<
<
<
<
<
<
<
<
<
<







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 },














    { "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
    { "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 */


    { "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 */







>
>







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
    { "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
     * 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!) */







|







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 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
};

/*
 * 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) },
    { NULL, 0, 0 }
};











/*
 * Dump error messages in the bit bucket.
 */

static void
TclDateerror(
    YYLTYPE* location,
    DateInfo* infoPtr,
    const char *s)
{
    Tcl_Obj* t;



    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
ToSeconds(
    time_t Hours,
    time_t Minutes,
    time_t 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;
    case MERam:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	}
	return ((Hours % 12) * 60L + Minutes) * 60L + Seconds;
    case MERpm:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	}
	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) {
	yylvalPtr->Meridian = MERam;
	return tMERIDIAN;
    }
    if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
	yylvalPtr->Meridian = MERpm;
	return tMERIDIAN;
    }

    /*
     * See if we have an abbreviation for a month.
     */







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


>
>
>
>
>
>
>
>
>
>












>
>
>
















|

|
|
|










|




|




|




















|



|







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
};

/*
 * Military timezone table.
 */

static const TABLE MilitaryTable[] = {
    { "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";
}

int
ToSeconds(
    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 * 60 + Minutes) * 60 + Seconds;
    case MERam:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	}
	return ((Hours % 12) * 60 + Minutes) * 60 + Seconds;
    case MERpm:
	if (Hours < 1 || Hours > 12) {
	    return -1;
	}
	return (((Hours % 12) + 12) * 60 + Minutes) * 60 + 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 (*buff == 'a' && (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0)) {
	yylvalPtr->Meridian = MERam;
	return tMERIDIAN;
    }
    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
    YYLTYPE* location,
    DateInfo *info)
{
    char c;
    char *p;
    char buff[20];
    int Count;


    location->first_column = yyInput - info->dateStart;
    for ( ; ; ) {
	while (TclIsSpaceProcM(*yyInput)) {



	    yyInput++;


	}



	if (isdigit(UCHAR(c = *yyInput))) { /* INTL: digit */

	    /*
	     * Convert the string into a number; count the number of digits.
	     */


	    Count = 0;

	    for (yylvalPtr->Number = 0;





		    isdigit(UCHAR(c = *yyInput++)); ) {	  /* INTL: digit */
		yylvalPtr->Number = 10 * yylvalPtr->Number + c - '0';
		Count++;

	    }

	    yyInput--;




	    yyDigitCount = Count;





	    /*
	     * 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;
	    } else {

		location->last_column = yyInput - info->dateStart - 1;
		return tUNUMBER;
	    }
	}




	if (!(c & 0x80) && isalpha(UCHAR(c))) {		  /* INTL: ISO only. */

	    for (p = buff; isalpha(UCHAR(c = *yyInput++)) /* INTL: ISO only. */
		     || c == '.'; ) {
		if (p < &buff[sizeof buff - 1]) {
		    *p++ = c;
		}
	    }
	    *p = '\0';
	    yyInput--;
	    location->last_column = yyInput - info->dateStart - 1;
	    return LookupWord(yylvalPtr, buff);






























	}
	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(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Count of paraneters */
    Tcl_Obj *const *objv)	/* 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]);
    dateInfo.dateStart = yyInput;

    yyHaveDate = 0;
    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;

    yyHaveOrdinalMonth = 0;
    yyMonthOrdinal = 0;

    yyHaveDay = 0;
    yyDayOrdinal = 0; yyDayNumber = 0;


    yyHaveRel = 0;
    yyRelMonth = 0; yyRelDay = 0; yyRelSeconds = 0; yyRelPointer = NULL;

    TclNewObj(dateInfo.messages);
    dateInfo.separatrix = "";
    Tcl_IncrRefCount(dateInfo.messages);

    status = yyparse(&dateInfo);
    if (status == 1) {
















	Tcl_SetObjResult(interp, dateInfo.messages);

	Tcl_DecrRefCount(dateInfo.messages);
	Tcl_SetErrorCode(interp, "TCL", "VALUE", "DATE", "PARSE", NULL);

	return 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;
    } 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_DecrRefCount(dateInfo.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;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>



|
>
>
>
|
>
>
|
|
>
>

>

|

|
>
|
>
|
>
>
>
>
>
|
|
<
>
|
>
|
>
>
>
>
|
>
>
>
|
>



<
<
|
>
>
|
<
>
|
|
|
|
>
>
>
>

>


|






|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



















|

|
<

<
|

<
<
<
<


|
|
|
|
|
|
|
<
|
|
<
<
<
<
<
<
|
<
<

<
|

<
|

|
<

>
|
<

<
<
<
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
|


<
|
|





<
|
|

>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|









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
    YYLTYPE* location,
    DateInfo *info)
{
    char c;
    char *p;
    char buff[20];
    int Count;
    const char *tokStart;

    location->first_column = yyInput - info->dateStart;
    for ( ; ; ) {

	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 */

	    /*
	     * Count the number of digits.
	     */
	    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) {

		    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.
	     */


	    location->last_column = yyInput - info->dateStart - 1;
	    if (yyDigitCount >= 6) {
		if (yyDigitCount == 8) {
		    return tISOBAS8;

		}
		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]) {
		    *p++ = c;
		}
	    }
	    *p = '\0';
	    yyInput--;
	    location->last_column = yyInput - info->dateStart - 1;
	    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
TclClockFreeScan(

    Tcl_Interp *interp,		/* Tcl interpreter */

    DateInfo *info)		/* Input and result parameters */
{




    int status;

  #if YYDEBUG
    /* enable debugging if compiled with YYDEBUG */
    yydebug = 1;
  #endif

    /*
     * yyInput = stringToParse;

     *
     * ClockInitDateInfo(info) should be executed to pre-init info;






     */




    yyDSTmode = DSTmaybe;


    info->separatrix = "";

    info->dateStart = yyInput;


    /* ignore spaces at begin */
    yyInput = bypassSpaces(yyInput);





    /* 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,
		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_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_SetErrorCode(interp, "TCL", "BUG", (char *)NULL);
	status = TCL_ERROR;
    }
    if (info->messages) {
	Tcl_DecrRefCount(info->messages);
    }

























































































    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
/*
 * 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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|
|







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 © 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

/*
 * 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);

/*
 * 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,







|








|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

/*
 * 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 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 size_t		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,
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288















289
290
291
292
293
294

295
296
297
298
299
300
301
	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;
	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;

	    }
	}
    } else {
	for (hPtr = tablePtr->buckets[index]; hPtr != NULL;
		hPtr = hPtr->nextPtr) {
	    if (hash != hPtr->hash) {
		continue;







|









|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
>







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
	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 = PTR2UINT(key);
	index = RANDOM_INDEX(tablePtr, hash);
    }

    /*
     * Search all of the entries in the appropriate bucket.
     */

    if (typePtr->compareKeysProc) {
	Tcl_CompareHashKeysProc *compareKeysProc = typePtr->compareKeysProc;
	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

void
Tcl_DeleteHashTable(
    Tcl_HashTable *tablePtr)	/* Table to delete. */
{
    Tcl_HashEntry *hPtr, *nextPtr;
    const Tcl_HashKeyType *typePtr;
    size_t 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) {







|







450
451
452
453
454
455
456
457
458
459
460
461
462
463
464

void
Tcl_DeleteHashTable(
    Tcl_HashTable *tablePtr)	/* Table to delete. */
{
    Tcl_HashEntry *hPtr, *nextPtr;
    const Tcl_HashKeyType *typePtr;
    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) {
583
584
585
586
587
588
589

590
591
592
593
594
595
596
597
 */

char *
Tcl_HashStats(
    Tcl_HashTable *tablePtr)	/* Table for which to produce stats. */
{
#define NUM_COUNTERS 10

    size_t count[NUM_COUNTERS], overflow, i, j;
    double average, tmp;
    Tcl_HashEntry *hPtr;
    char *result, *p;

    /*
     * Compute a histogram of bucket usage.
     */







>
|







599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
 */

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, 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
    }

    /*
     * 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",
	    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",
		i, count[i]);
	p += strlen(p);
    }
    sprintf(p, "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);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * AllocArrayEntry --







|



|



|


|







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
    }

    /*
     * Print out the histogram and a few other pieces of information.
     */

    result = (char *)Tcl_Alloc((NUM_COUNTERS * 60) + 300);
    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++) {
	snprintf(p, 60, "number of buckets with %" TCL_SIZE_MODIFIER "u entries: %" TCL_SIZE_MODIFIER "u\n",
		i, count[i]);
	p += strlen(p);
    }
    snprintf(p, 60, "number of buckets with %d or more entries: %" TCL_SIZE_MODIFIER "u\n",
	    NUM_COUNTERS, overflow);
    p += strlen(p);
    snprintf(p, 60, "average search distance for entry: %.1f", average);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * AllocArrayEntry --
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
 */

static Tcl_HashEntry *
AllocArrayEntry(
    Tcl_HashTable *tablePtr,	/* Hash table. */
    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;

    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;
	    count > 0; count--, iPtr1++, iPtr2++) {
	*iPtr2 = *iPtr1;
    }
    Tcl_SetHashValue(hPtr, NULL);

    return hPtr;
}

/*
 *----------------------------------------------------------------------







<
<

|
|

<
<
<





|
<
<
<







671
672
673
674
675
676
677


678
679
680
681



682
683
684
685
686
687



688
689
690
691
692
693
694
 */

static Tcl_HashEntry *
AllocArrayEntry(
    Tcl_HashTable *tablePtr,	/* Hash table. */
    void *keyPtr)			/* Key to store in the hash table entry. */
{


    Tcl_HashEntry *hPtr;
    size_t count = tablePtr->keyType * sizeof(int);
    size_t size = offsetof(Tcl_HashEntry, key) + count;




    if (size < sizeof(Tcl_HashEntry)) {
	size = sizeof(Tcl_HashEntry);
    }
    hPtr = (Tcl_HashEntry *)Tcl_Alloc(size);

    memcpy(hPtr->key.string, keyPtr, count);



    Tcl_SetHashValue(hPtr, NULL);

    return hPtr;
}

/*
 *----------------------------------------------------------------------
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
 */

static int
CompareArrayKeys(
    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;
    int count;

    for (count = tablePtr->keyType; ; count--, iPtr1++, iPtr2++) {
	if (count == 0) {
	    return 1;
	}
	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
HashArrayKey(
    Tcl_HashTable *tablePtr,	/* Hash table. */
    void *keyPtr)				/* Key from which to compute hash value. */
{
    const int *array = (const int *) keyPtr;
    TCL_HASH_TYPE result;
    int count;

    for (result = 0, count = tablePtr->keyType; count > 0;
	    count--, array++) {
	result += *array;
    }
    return result;







<
<
|
<

<
<
|
<
<
<
<
<
<




















|





|







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
 */

static int
CompareArrayKeys(
    void *keyPtr,			/* New key to compare. */
    Tcl_HashEntry *hPtr)	/* Existing key to compare. */
{


    size_t count = hPtr->tablePtr->keyType * sizeof(int);




    return !memcmp(keyPtr, hPtr->key.string, count);






}

/*
 *----------------------------------------------------------------------
 *
 * 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 size_t
HashArrayKey(
    Tcl_HashTable *tablePtr,	/* Hash table. */
    void *keyPtr)				/* Key from which to compute hash value. */
{
    const int *array = (const int *) keyPtr;
    size_t result;
    int count;

    for (result = 0, count = tablePtr->keyType; count > 0;
	    count--, array++) {
	result += *array;
    }
    return result;
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
    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));
    memcpy(hPtr->key.string, string, size);
    Tcl_SetHashValue(hPtr, NULL);
    return hPtr;
}

/*
 *----------------------------------------------------------------------







|







777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
    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, offsetof(Tcl_HashEntry, key) + allocsize);
    memcpy(hPtr->key.string, string, size);
    Tcl_SetHashValue(hPtr, NULL);
    return hPtr;
}

/*
 *----------------------------------------------------------------------
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static TCL_HASH_TYPE
HashStringKey(
    TCL_UNUSED(Tcl_HashTable *),
    void *keyPtr)			/* Key from which to compute hash value. */
{
    const char *string = (const char *)keyPtr;
    TCL_HASH_TYPE 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







|





|







825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static size_t
HashStringKey(
    TCL_UNUSED(Tcl_HashTable *),
    void *keyPtr)			/* Key from which to compute hash value. */
{
    const char *string = (const char *)keyPtr;
    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
/*
 * 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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"









|
|







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 © 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
 *	The constant words may be deleted.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteHistoryObjs(
    ClientData clientData,
    TCL_UNUSED(Tcl_Interp *))
{
    HistoryObjs *histObjsPtr = (HistoryObjs *)clientData;

    TclDecrRefCount(histObjsPtr->historyObj);
    TclDecrRefCount(histObjsPtr->addObj);
    Tcl_Free(histObjsPtr);







|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
 *	The constant words may be deleted.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteHistoryObjs(
    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
/*
 * 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.
 * 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"






|
|







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 © 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
 */

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. */
    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







|







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. */
    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
 * 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. */
    struct NextChannelHandler *nestedHandlerPtr;
					/* Next nested invocation of
					 * Tcl_NotifyChannel. */
} NextChannelHandler;

/*
 * The following structure is used by Tcl_GetsObj() to encapsulates the
 * state for a "gets" operation.
 */








|
>
|

|
|







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. */
    struct NextChannelHandler *nestedHandlerPtr;
				/* Next nested invocation of
				 * Tcl_NotifyChannel. */
} NextChannelHandler;

/*
 * The following structure is used by Tcl_GetsObj() to encapsulates the
 * state for a "gets" operation.
 */

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    struct Channel *writePtr;	/* Pointer to output channel. */
    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. */
} 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.







|
|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
    struct Channel *writePtr;	/* Pointer to output channel. */
    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. */
    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.
121
122
123
124
125
126
127
128
129
130
131
132
133



134
135
136
137
138
139
140
141
142
143
144
145
146
147

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167

168
169
170
171
172
173
174



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
				/* 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;



} 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. */

} CloseCallback;

/*
 * Static functions in this file:
 */

static ChannelBuffer *	AllocChannelBuffer(int 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 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 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		CopyEventProc(ClientData clientData, int mask);
static void		CreateScriptRecord(Tcl_Interp *interp,
			    Channel *chanPtr, int mask, Tcl_Obj *scriptPtr);
static void		DeleteChannelTable(ClientData 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,
			    int allowShortReads);
static int		DoReadChars(Channel *chan, Tcl_Obj *objPtr, size_t toRead,
			    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 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		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_Obj *	FixLevelCode(Tcl_Obj *msg);
static void		SpliceChannel(Tcl_Channel chan);
static void		CutChannel(Tcl_Channel chan);
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)
 *
 *	Returns the number of bytes of data remaining in the buffer.
 *
 * int SpaceLeft(ChannelBuffer *bufPtr)
 *
 *	Returns the number of bytes of space remaining at the end of the
 *	buffer.







<

<

<

>
>
>










|
|
|
|
>






|




|








>







>
>
>






|

|


|







|

|
|






|

















|
|
















|







122
123
124
125
126
127
128

129

130

131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
				/* 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. */

    Tcl_Channel stdoutChannel;	/* Static variable for the stdout channel. */

    Tcl_Channel stderrChannel;	/* Static variable for the stderr channel. */

    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. */
    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(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(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 void		CleanupTimerHandler(ChannelState *statePtr);
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(void *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(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 Tcl_Size		DoRead(Channel *chanPtr, char *dst, Tcl_Size bytesToRead,
			    int allowShortReads);
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 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		TranslateInputEOL(ChannelState *statePtr, char *dst,
			    const char *src, int *dstLenPtr, int *srcLenPtr);
static void		UpdateInterest(Channel *chanPtr);
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);

#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.
 *
 * --------------------------------------------------------------------------
 * Tcl_Size BytesLeft(ChannelBuffer *bufPtr)
 *
 *	Returns the number of bytes of data remaining in the buffer.
 *
 * int SpaceLeft(ChannelBuffer *bufPtr)
 *
 *	Returns the number of bytes of space remaining at the end of the
 *	buffer.
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
 * 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 SpaceLeft(bufPtr)	((size_t)((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)








|

|







277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
 * char *RemovePoint(ChannelBuffer *bufPtr)
 *
 *	Returns a pointer to where characters should be removed from the
 *	buffer.
 * --------------------------------------------------------------------------
 */

#define BytesLeft(bufPtr)	((bufPtr)->nextAdded - (bufPtr)->nextRemoved)

#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)

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
    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
				 * 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 const Tcl_ObjType chanObjType = {
    "channel",			/* name for this type */
    FreeChannelIntRep,		/* freeIntRepProc */
    DupChannelIntRep,		/* dupIntRepProc */
    NULL,			/* updateStringProc */
    NULL			/* setFromAnyProc */

};




#define ChanSetIntRep(objPtr, resPtr)					\
    do {								\
	Tcl_ObjIntRep ir;						\
	(resPtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (resPtr);					\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &chanObjType, &ir);			\
    } while (0)

#define ChanGetIntRep(objPtr, resPtr)					\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((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)))








|
|



|
|

|
>


>
>
>
|

|



|


|

|
|







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
    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
				 * was done. Use to verify validity. */
    size_t refCount;		/* Share this struct among many Tcl_Obj. */
} ResolvedChanName;

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 */
    FreeChannelInternalRep,		/* freeIntRepProc */
    DupChannelInternalRep,		/* dupIntRepProc */
    NULL,			/* updateStringProc */
    NULL,			/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define GetIso88591() \
    (binaryEncoding ? Tcl_GetEncoding(NULL, "iso8859-1") : binaryEncoding)

#define ChanSetInternalRep(objPtr, resPtr)					\
    do {								\
	Tcl_ObjInternalRep ir;						\
	(resPtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (resPtr);					\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreInternalRep((objPtr), &chanObjType, &ir);			\
    } while (0)

#define ChanGetInternalRep(objPtr, resPtr)					\
    do {								\
	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
 * 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.
 *
 *	TODO - Is this really the right place for that?
 *
 *---------------------------------------------------------------------------
 */
static int
ChanRead(







|
|
|







398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
 * 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_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(
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
    /*
     * 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_ChannelWideSeekProc(chanPtr->typePtr)(chanPtr->instanceData,
		offset, mode, errnoPtr);
}

static inline void







|







485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
    /*
     * 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 TCL_INDEX_NONE;
    }

	return Tcl_ChannelWideSeekProc(chanPtr->typePtr)(chanPtr->instanceData,
		offset, mode, errnoPtr);
}

static inline void
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
		statePtr != NULL;
		statePtr = statePtr->nextCSPtr) {
	    chanPtr = statePtr->topChanPtr;
            if (GotFlag(statePtr, CHANNEL_DEAD)) {
                continue;
            }
	    if (!GotFlag(statePtr, CHANNEL_INCLOSE | CHANNEL_CLOSED )
                || GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
                ResetFlag(statePtr, BG_FLUSH_SCHEDULED);
		active = 1;
		break;
	    }
	}

	/*







|







615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
		statePtr != NULL;
		statePtr = statePtr->nextCSPtr) {
	    chanPtr = statePtr->topChanPtr;
            if (GotFlag(statePtr, CHANNEL_DEAD)) {
                continue;
            }
	    if (!GotFlag(statePtr, CHANNEL_INCLOSE | CHANNEL_CLOSED )
		    || GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
                ResetFlag(statePtr, BG_FLUSH_SCHEDULED);
		active = 1;
		break;
	    }
	}

	/*
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
            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");
            }

	    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) {
		/*
		 * 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);







|













|







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
            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");
            }

	    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 <= 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
		chanPtr->instanceData = NULL;
		SetFlag(statePtr, CHANNEL_DEAD);
	    }
	    TclChannelRelease((Tcl_Channel)chanPtr);
	}
    }


    TclpFinalizeSockets();
    TclpFinalizePipes();
}

/*
 *----------------------------------------------------------------------
 *







>







693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
		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
    case TCL_STDOUT:
	tsdPtr->stdoutInitialized = init;
	tsdPtr->stdoutChannel = channel;
	break;
    case TCL_STDERR:
	tsdPtr->stderrInitialized = init;
	tsdPtr->stderrChannel = channel;




	break;
    }
}

/*
 *----------------------------------------------------------------------
 *







>
>
>
>







735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
    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
	channel = tsdPtr->stdoutChannel;
	break;
    case TCL_STDERR:
	if (!tsdPtr->stderrInitialized) {
	    tsdPtr->stderrInitialized = -1;
	    tsdPtr->stderrChannel = TclpGetDefaultStdChannel(TCL_STDERR);
	    if (tsdPtr->stderrChannel != NULL) {


		tsdPtr->stderrInitialized = 1;
		Tcl_RegisterChannel(NULL, tsdPtr->stderrChannel);
	    }
	}
	channel = tsdPtr->stderrChannel;
	break;
    }







>
>







809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
	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

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
				 * callback. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
    CloseCallback *cbPtr;

    cbPtr = (CloseCallback *)Tcl_Alloc(sizeof(CloseCallback));
    cbPtr->proc = proc;







|







845
846
847
848
849
850
851
852
853
854
855
856
857
858
859

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. */
    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

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
				 * remove. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
    CloseCallback *cbPtr, *cbPrevPtr;

    for (cbPtr = statePtr->closeCbPtr, cbPrevPtr = NULL;
	    cbPtr != NULL; cbPtr = cbPtr->nextPtr) {







|







883
884
885
886
887
888
889
890
891
892
893
894
895
896
897

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. */
    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
 *	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
 *	registered in this interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteChannelTable(
    ClientData 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. */







|







|







974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
 *	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 channelEvent handlers that were
 *	registered in this interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteChannelTable(
    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
    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.
	 */

	for (sPtr = statePtr->scriptRecordPtr, prevPtr = NULL;
		sPtr != NULL; sPtr = nextPtr) {
	    nextPtr = sPtr->nextPtr;
	    if (sPtr->interp == interp) {
		if (prevPtr == NULL) {







|







1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
    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 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
{
    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) {
	    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) {
	    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) {
	    statePtr->refCount = 0;
	    tsdPtr->stderrChannel = NULL;
	    return;
	}
    }
}








|







|







|







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
{
    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 < 2) {
	    statePtr->refCount = 0;
	    tsdPtr->stdinChannel = NULL;
	    return;
	}
    } else if (tsdPtr->stdoutInitialized == 1
	    && tsdPtr->stdoutChannel != NULL
	    && statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) {
	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 < 2) {
	    statePtr->refCount = 0;
	    tsdPtr->stderrChannel = NULL;
	    return;
	}
    }
}

1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257

    CheckForStdChannelsBeingClosed(chan);

    /*
     * If the refCount reached zero, close the actual channel.
     */

    if (statePtr->refCount + 1 <= 1) {
	Tcl_Preserve(statePtr);
	if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) {
	    /*
	     * We don't want to re-enter Tcl_CloseEx().
	     */

	    if (!GotFlag(statePtr, CHANNEL_CLOSED)) {







|







1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274

    CheckForStdChannelsBeingClosed(chan);

    /*
     * If the refCount reached zero, close the actual channel.
     */

    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

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
				 * 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. */







|







1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440

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 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. */
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
    }

    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);
	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);
    }

    return (Tcl_Channel) chanPtr;
}

/*
 *---------------------------------------------------------------------------







|












|







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
    }

    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, (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 = 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
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
				 * 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);
    if (resPtr) {
	/*
 	 * Confirm validity of saved lookup results.
 	 */

	statePtr = resPtr->statePtr;
	if ((resPtr->interp == interp)		/* Same interp context */







|












|







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
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 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;
    }

    ChanGetInternalRep(objPtr, resPtr);
    if (resPtr) {
	/*
 	 * Confirm validity of saved lookup results.
 	 */

	statePtr = resPtr->statePtr;
	if ((resPtr->interp == interp)		/* Same interp context */
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
	}
    }

    chan = Tcl_GetChannel(interp, TclGetString(objPtr), NULL);

    if (chan == NULL) {
	if (resPtr) {
	    Tcl_StoreIntRep(objPtr, &chanObjType, NULL);
	}
	return TCL_ERROR;
    }

    if (resPtr && resPtr->refCount == 1) {
	/*
         * 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 */
    }
    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);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|













|











|







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
	}
    }

    chan = Tcl_GetChannel(interp, TclGetString(objPtr), NULL);

    if (chan == NULL) {
	if (resPtr) {
	    Tcl_StoreInternalRep(objPtr, &chanObjType, NULL);
	}
	return TCL_ERROR;
    }

    if (resPtr && resPtr->refCount == 1) {
	/*
         * Re-use the ResolvedCmdName struct.
         */

	Tcl_Release(resPtr->statePtr);
    } else {
	resPtr = (ResolvedChanName *) Tcl_Alloc(sizeof(ResolvedChanName));
	resPtr->refCount = 0;
	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 = 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
 *----------------------------------------------------------------------
 */

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. */
    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
     * 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)) {







|










<
<
<
<
<
<
>
|
<
<
|
<
<







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
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_CreateChannel(
    const Tcl_ChannelType *typePtr, /* The channel type record. */
    const char *chanName,	/* Name of channel to record. */
    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);







    if (typePtr->typeName == NULL) {
	Tcl_Panic("channel does not have a type name");


    }


    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)) {
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
	strcpy(tmp, chanName);
    } else {
	tmp = (char *)Tcl_Alloc(7);
	tmp[0] = '\0';
    }
    statePtr->channelName = tmp;
    statePtr->flags = mask;


    /*
     * 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->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->csPtrR		= NULL;
    statePtr->csPtrW		= NULL;
    statePtr->outputStage	= NULL;

    /*
     * As we are creating the channel, it is obviously the top for now.
     */







>











<

<
|
<
















<















>







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
	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.
     */


    name = Tcl_GetEncodingName(NULL);

    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->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

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
				 * 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;







|







1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820

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. */
    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;
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
     *	- |   |   |   |    |
     *	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 (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "reading and writing both disallowed for channel \"%s\"",
		    Tcl_GetChannelName(prevChan)));
	}
	return NULL;
    }







|







1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
     *	- |   |   |   |    |
     *	R |   | + |   | +  |	The superceding channel is allowed to restrict
     *	W |   |   | + | +  |	the capabilities of the superceded one!
     *	RW|   | + | + | +  |
     *	--+---+---+---+----+
     */

    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;
    }
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
     * 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
     * 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.







|







1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
     * 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 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
    }
}

static void
ChannelFree(
    Channel *chanPtr)
{
    if (!chanPtr->refCount) {
	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
 *	Tcl_SetErrno. May leave a message in interp result as well.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UnstackChannel(







|


















|







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
    }
}

static void
ChannelFree(
    Channel *chanPtr)
{
    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
 *	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
     * 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
	 * 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







|







2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
     * 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/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
2136
2137
2138
2139
2140
2141
2142

2143
2144


2145
2146
2147
2148
2149
2150
2151
	/*
	 * Leave this link intact for closeproc
	 *  chanPtr->downChanPtr = NULL;
	 */

	/*
	 * Close and free the channel driver state.

	 */



	result = ChanClose(chanPtr, interp);
	ChannelFree(chanPtr);

	UpdateInterest(statePtr->topChanPtr);

	if (result != 0) {
	    Tcl_SetErrno(result);







>


>
>







2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
	/*
	 * 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
	}
    } else {
	/*
	 * This channel does not cover another one. Simply do a close, if
	 * necessary.
	 */

	if (statePtr->refCount + 1 <= 1) {
	    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".
		 */








|







2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
	}
    } else {
	/*
	 * This channel does not cover another one. Simply do a close, if
	 * necessary.
	 */

	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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
Tcl_GetChannelInstanceData(
    Tcl_Channel chan)		/* Channel for which to return client data. */
{
    Channel *chanPtr = (Channel *) chan;
				/* The actual channel. */

    return chanPtr->instanceData;







|







2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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
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));
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetChannelName --
 *







|







2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
Tcl_GetChannelMode(
    Tcl_Channel chan)		/* The channel for which the mode is being
				 * computed. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of actual channel. */

    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
 *----------------------------------------------------------------------
 */

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 */
{
    Channel *chanPtr;		/* The actual channel. */
    ClientData 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)));
	return TCL_ERROR;
    }
    result = chanPtr->typePtr->getHandleProc(chanPtr->instanceData, direction,
	    &handle);
    if (handlePtr) {
	*handlePtr = handle;
    }
    return result;
}

















































/*
 *---------------------------------------------------------------------------
 *
 * AllocChannelBuffer --
 *
 *	A channel buffer has BUFFER_PADDING bytes extra at beginning to hold







|


|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *----------------------------------------------------------------------
 */

int
Tcl_GetChannelHandle(
    Tcl_Channel chan,		/* The channel to get file from. */
    int direction,		/* TCL_WRITABLE or TCL_READABLE. */
    void **handlePtr)	/* Where to store handle */
{
    Channel *chanPtr;		/* The actual channel. */
    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)));
	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
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static ChannelBuffer *
AllocChannelBuffer(
    int length)			/* Desired length of channel buffer. */
{
    ChannelBuffer *bufPtr;
    int 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;







|


|







2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static ChannelBuffer *
AllocChannelBuffer(
    Tcl_Size length)			/* Desired length of channel buffer. */
{
    ChannelBuffer *bufPtr;
    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
    Tcl_Free(bufPtr);
}

static int
IsShared(
    ChannelBuffer *bufPtr)
{
    return bufPtr->refCount + 1 > 2;
}

/*
 *----------------------------------------------------------------------
 *
 * RecycleBuffer --
 *







|







2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
    Tcl_Free(bufPtr);
}

static int
IsShared(
    ChannelBuffer *bufPtr)
{
    return bufPtr->refCount > 1;
}

/*
 *----------------------------------------------------------------------
 *
 * RecycleBuffer --
 *
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542

    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.
     */

    if ((bufPtr->bufLength - BUFFER_PADDING) != statePtr->bufSize) {
	ReleaseChannelBuffer(bufPtr);
	return;
    }

    /*
     * Only save buffers for the input queue if the channel is readable.
     */







|
|


|







2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599

    if (mustDiscard) {
	ReleaseChannelBuffer(bufPtr);
	return;
    }

    /*
     * 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) != statePtr->bufSize + BUFFER_PADDING) {
	ReleaseChannelBuffer(bufPtr);
	return;
    }

    /*
     * Only save buffers for the input queue if the channel is readable.
     */
2681
2682
2683
2684
2685
2686
2687

2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
    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. */


    /*
     * 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
     * interpreters.
     */

    if (CheckForDeadChannel(interp, statePtr)) {
	return -1;
    }








>



|







2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
    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 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
	    /*
	     * 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
		 * the unreported area. Or discard it if the new error is to
		 * be ignored in favor of an earlier defered error.
		 */

		Tcl_Obj *msg = statePtr->chanMsg;

		if (statePtr->unreportedError == 0) {
		    statePtr->unreportedError = errorCode;
		    statePtr->unreportedMsg = msg;







|

|







2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
	    /*
	     * Decide whether to report the error upwards or defer it.
	     */

	    if (calledFromAsyncFlush) {
		/*
		 * TIP #219, Tcl Channel Reflection API.
		 * 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 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
	    }

	    /*
	     * When we get an error we throw away all the output currently
	     * queued.
	     */

	    DiscardOutputQueued(statePtr);
	    ReleaseChannelBuffer(bufPtr);

	    break;
	} else {
	    /*
	     * TODO: Consider detecting and reacting to short writes on
	     * blocking channels.  Ought not happen.  See iocmd-24.2.
	     */

	    wroteSome = 1;
	}












	bufPtr->nextRemoved += written;

	/*
	 * 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);
    }	/* 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.







<

>










>
>
>
>
>
>
>
>
>
>
>
|

|
|
|

|
|
|
|
|
|
|
>
|







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
	    }

	    /*
	     * When we get an error we throw away all the output currently
	     * queued.
	     */


	    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;

	    /*
	     * 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);
	    }
	}

    }	/* 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

    /*
     * 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) &&
	    (statePtr->outQueueHead == NULL) &&
	    ((statePtr->curOutPtr == NULL) ||
	    IsBufferEmpty(statePtr->curOutPtr))) {
	errorCode = CloseChannel(interp, chanPtr, errorCode);
	goto done;
    }








|







2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001

    /*
     * 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 <= 0) &&
	    (statePtr->outQueueHead == NULL) &&
	    ((statePtr->curOutPtr == NULL) ||
	    IsBufferEmpty(statePtr->curOutPtr))) {
	errorCode = CloseChannel(interp, chanPtr, errorCode);
	goto done;
    }

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
     * 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) {







<
<
<
<
<
<
<
<
<
<
<
<







3077
3078
3079
3080
3081
3082
3083












3084
3085
3086
3087
3088
3089
3090
     * The caller guarantees that there are no more buffers queued for output.
     */

    if (statePtr->outQueueHead != NULL) {
	Tcl_Panic("TclFlush, closed channel: queued output left");
    }













    /*
     * 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) {
3092
3093
3094
3095
3096
3097
3098

3099
3100
3101
3102
3103
3104
3105
3106
3107
	    Tcl_SetErrno(errorCode);
	}
    }

    /*
     * Cancel any outstanding timer.
     */


    Tcl_DeleteTimerHandler(statePtr->timer);

    /*
     * Mark the channel as deleted by clearing the type structure.
     */

    if (chanPtr->downChanPtr != NULL) {
	Channel *downChanPtr = chanPtr->downChanPtr;







>

<







3150
3151
3152
3153
3154
3155
3156
3157
3158

3159
3160
3161
3162
3163
3164
3165
	    Tcl_SetErrno(errorCode);
	}
    }

    /*
     * Cancel any outstanding timer.
     */
    DeleteTimerHandler(statePtr);



    /*
     * Mark the channel as deleted by clearing the type structure.
     */

    if (chanPtr->downChanPtr != NULL) {
	Channel *downChanPtr = chanPtr->downChanPtr;
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
 * 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.
 *
 *----------------------------------------------------------------------
 */

static void
CutChannel(
    Tcl_Channel chan)		/* The channel being removed. Must not be







|
|







3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
 * 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 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
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

static void
SpliceChannel(
    Tcl_Channel chan)		/* The channel being added. Must not be







|
|
|







3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
 *
 * 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 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
 *----------------------------------------------------------------------
 */

int
TclClose(
    Tcl_Interp *interp,		/* Interpreter for errors. */
    Tcl_Channel chan)		/* The channel being closed. Must not be
				 * referenced in any interpreter. */

{
    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;







|
>







3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
 *----------------------------------------------------------------------
 */

int
TclClose(
    Tcl_Interp *interp,		/* Interpreter for errors. */
    Tcl_Channel chan)		/* The channel being closed. Must not be
				 * 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
     * 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) {
	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));
	}
	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)

	    && !(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;







|




















|
>







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
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = (Channel *) chan;
    statePtr = chanPtr->state;
    chanPtr = statePtr->topChanPtr;

    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));
	}
	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 != 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;
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
    }

    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;







|







3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
    }

    Tcl_ClearChannelHandlers(chan);

    /*
     * Cancel any outstanding timer.
     */
    DeleteTimerHandler(statePtr);

    /*
     * Invoke the registered close callbacks and delete their records.
     */

    while (statePtr->closeCbPtr != NULL) {
	cbPtr = statePtr->closeCbPtr;
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
	result = EINVAL;
    }

    if (stickyError != 0) {
	Tcl_SetErrno(stickyError);
	if (interp != NULL) {
	    Tcl_SetObjResult(interp,
			     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.







|







3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
	result = EINVAL;
    }

    if (stickyError != 0) {
	Tcl_SetErrno(stickyError);
	if (interp != NULL) {
	    Tcl_SetObjResult(interp,
		    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

    /*
     * 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)) {
	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));
	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 (interp) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
                    "illegal recursive call to close through close-handler"
                    " of channel", -1));
	}
	return TCL_ERROR;
    }







|


















|







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

    /*
     * 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 (!(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));
	return TCL_ERROR;
    }

    /*
     * A user may try to call half-close from within a channel close handler.
     * That won't do.
     */

    if (GotFlag(statePtr, CHANNEL_INCLOSE)) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
                    "illegal recursive call to close through close-handler"
                    " of channel", -1));
	}
	return TCL_ERROR;
    }
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
 *	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
 *	longer if it has a background flush scheduled. The device itself is
 *	eventually closed and the channel structures modified, in
 *	CloseChannelPart, below.
 *
 *----------------------------------------------------------------------
 */








|







3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
 *	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 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.
 *
 *----------------------------------------------------------------------
 */

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
	 */

	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) {







<
<
<
<
<
<
<
<
<
<
<
<







3842
3843
3844
3845
3846
3847
3848












3849
3850
3851
3852
3853
3854
3855
	 */

	if (statePtr->outQueueHead != NULL) {
	    Tcl_Panic("ClosechanHalf, closed write-side of channel: "
		    "queued output left");
	}













	/*
	 * 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) {
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
    chanPtr = (Channel *) channel;
    statePtr = chanPtr->state;
    chanPtr = statePtr->topChanPtr;

    /*
     * Cancel any outstanding timer.
     */

    Tcl_DeleteTimerHandler(statePtr->timer);

    /*
     * Remove any references to channel handlers for this channel that may be
     * about to be invoked.
     */

    for (nhPtr = tsdPtr->nestedHandlerPtr; nhPtr != NULL;







<
|







3957
3958
3959
3960
3961
3962
3963

3964
3965
3966
3967
3968
3969
3970
3971
    chanPtr = (Channel *) channel;
    statePtr = chanPtr->state;
    chanPtr = statePtr->topChanPtr;

    /*
     * Cancel any outstanding 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;
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
 *	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.
 *
 * Side effects:
 *	May buffer up output and may cause output to be produced on the
 *	channel.
 *
 *----------------------------------------------------------------------
 */

size_t
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
				 * 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;
    }

    if (srcLen == TCL_INDEX_NONE) {
	srcLen = strlen(src);
    }
    if (WriteBytes(chanPtr, src, srcLen) == -1) {
	return TCL_IO_FAILURE;
    }
    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.
 *
 * Side effects:
 *	May buffer up output and may cause output to be produced on the
 *	channel.
 *
 *----------------------------------------------------------------------
 */

size_t
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
				 * strlen(). */
{
    Channel *chanPtr = ((Channel *) chan);
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    int errorCode;
    size_t written;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE | CHANNEL_RAW_MODE) != 0) {
	return TCL_IO_FAILURE;
    }

    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) {
	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.
 *
 * Side effects:
 *	May buffer up output and may cause output to be produced on the
 *	channel.
 *
 *----------------------------------------------------------------------
 */

size_t
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
				 * strlen(). */
{
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;	/* State info for channel */
    int result;
    Tcl_Obj *objPtr;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
	return TCL_IO_FAILURE;
    }

    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
     * 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);

    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.
 *
 * Side effects:
 *	May buffer up output and may cause output to be produced on the
 *	channel.
 *
 *----------------------------------------------------------------------
 */

size_t
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;

    statePtr = ((Channel *) chan)->state;
    chanPtr = statePtr->topChanPtr;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
	return TCL_IO_FAILURE;
    }
    if (statePtr->encoding == NULL) {

	src = (char *) TclGetByteArrayFromObj(objPtr, &srcLen);





	return WriteBytes(chanPtr, src, srcLen);


    } 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)){
	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)) {
	/*
	 * 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 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,
 *	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
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_Encoding encoding)
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    char *nextNewLine = NULL;

    int endEncoding, saved = 0, total = 0, flushed = 0, needNlFlush = 0;



    if (srcLen) {
        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) {
	ChannelBuffer *bufPtr;
	char *dst, safe[BUFFER_PADDING];
	int result, srcRead, dstLen, dstWrote, srcLimit = srcLen;


	if (nextNewLine) {
	    srcLimit = nextNewLine - src;
	}

	/* Get space to write into */
	bufPtr = statePtr->curOutPtr;







|
|








|



|













|






|


















|
|








|



|






|


|












|



















|
|








|




|




|



|














|








|
>
>
>
>
|
>



















|
|








|











|





|


>
|
>
>
>
>
>
|
>
>












|
|




















|
|











|
















|









|



|





>
|
>
>










<





|

|
|
>







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
 *	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_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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_Write(
    Tcl_Channel chan,		/* The channel to buffer output for. */
    const char *src,		/* Data to queue in output buffer. */
    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_INDEX_NONE;
    }

    if (srcLen == TCL_INDEX_NONE) {
	srcLen = strlen(src);
    }
    if (WriteBytes(chanPtr, src, srcLen) == -1) {
	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_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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_WriteRaw(
    Tcl_Channel chan,		/* The channel to buffer output for. */
    const char *src,		/* Data to queue in output buffer. */
    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;
    Tcl_Size written;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE | CHANNEL_RAW_MODE) != 0) {
	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_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_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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_WriteChars(
    Tcl_Channel chan,		/* The channel to buffer output for. */
    const char *src,		/* UTF-8 characters to queue in output
				 * buffer. */
    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 */
    Tcl_Size result;
    Tcl_Obj *objPtr;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
	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 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 *) 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 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.
 *
 *----------------------------------------------------------------------
 */

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;
    Tcl_Size srcLen = 0;

    statePtr = ((Channel *) chan)->state;
    chanPtr = statePtr->topChanPtr;

    if (CheckChannelErrors(statePtr, TCL_WRITABLE) != 0) {
	return TCL_INDEX_NONE;
    }
    if (statePtr->encoding == NULL) {
	Tcl_Size result;

	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)){
	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)) {
	/*
	 * 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 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 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 Tcl_Size
Write(
    Channel *chanPtr,		/* The channel to buffer output for. */
    const char *src,		/* UTF-8 string to write. */
    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;
    Tcl_Size saved = 0, total = 0, flushed = 0;
    char safe[BUFFER_PADDING];
    int encodingError = 0;

    if (srcLen) {
        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 && !encodingError) {
	ChannelBuffer *bufPtr;
	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
	     * 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;








	if ((result != TCL_OK) && (srcRead + dstWrote == 0)) {

	    /*
	     * We're reading from invalid/incomplete UTF-8.
	     */

	    ReleaseChannelBuffer(bufPtr);
	    if (total == 0) {
		Tcl_SetErrno(EINVAL);
		return -1;
	    }
	    break;
	}

	bufPtr->nextAdded += dstWrote;
	src += srcRead;
	srcLen -= srcRead;
	total += dstWrote;
	dst += dstWrote;







<














>
>
>
>
>
>
>
|
>
|
|
|
|
<
<
|
<
<
|







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
	     * that we need to stick at the beginning of this buffer.
	     */

	    memcpy(InsertPoint(bufPtr), safe, saved);
	    bufPtr->nextAdded += saved;
	    saved = 0;
	}

	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_CONVERT_UNKNOWN || result == TCL_CONVERT_SYNTAX) ||
		/*
		 * We're reading from invalid/incomplete UTF-8.
		 */
		((result != TCL_OK) && (srcRead + dstWrote == 0))) {


	    encodingError = 1;


	    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
	     * 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);
	    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.
 	     */

	    if (needNlFlush && (saved == 0 || src[-1] != '\n')) {
		needNlFlush = 0;
	    }
	}
	ReleaseChannelBuffer(bufPtr);
    }
    if ((flushed < total) && (GotFlag(statePtr, CHANNEL_UNBUFFERED) ||
	    (needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED)))) {
	if (FlushChannel(NULL, chanPtr, 0) != 0) {
	    return -1;
	}
    }

    UpdateInterest(chanPtr);





    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
 *	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_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;

    TclNewObj(objPtr);
    charsStored = Tcl_GetsObj(chan, objPtr);
    if (charsStored + 1 > 1) {
	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
 *	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_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_Encoding encoding;
    char *dst, *dstEnd, *eol, *eof;
    Tcl_EncodingState oldState;








    if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
	return TCL_IO_FAILURE;
    }

    /*
     * 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;
    }

    /*
     * 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)
	    && ((statePtr->inputTranslation == TCL_TRANSLATE_LF)
		    || (statePtr->inputTranslation == TCL_TRANSLATE_CR))) {

	return TclGetsObjBinary(chan, objPtr);
    }

    /*
     * This operation should occur at the top of a channel stack.
     */








|










<






|












<

|
|







>
>
>
>











|
|









|








|



|
















|
|











|











|




>
>
>
>
>
>
>

|














|








|

|
>







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
	     * 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 = -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) {

		return -1;
	    }
	    flushed += statePtr->bufSize;

	    /*
 	     * 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;
	    }
	}

    }
    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 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.
 *
 *---------------------------------------------------------------------------
 */

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;
    Tcl_Size charsStored;

    TclNewObj(objPtr);
    charsStored = Tcl_GetsObj(chan, objPtr);
    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 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.
 *
 *---------------------------------------------------------------------------
 */

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;
    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_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_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 == GetBinaryEncoding()
	    && ((statePtr->inputTranslation == TCL_TRANSLATE_LF)
		    || (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
    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;







<
<
<
<
<
<
<
<
<







4653
4654
4655
4656
4657
4658
4659









4660
4661
4662
4663
4664
4665
4666
    oldFlags = statePtr->inputEncodingFlags;
    oldState = statePtr->inputEncodingState;
    oldRemoved = BUFFER_PADDING;
    if (bufPtr != NULL) {
	oldRemoved = bufPtr->nextRemoved;
    }










    /*
     * 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
    skip = 0;
    eof = NULL;
    inEofChar = statePtr->inEofChar;

    ResetFlag(statePtr, CHANNEL_BLOCKED);
    while (1) {
	if (dst >= dstEnd) {






	    if (FilterInputBytes(chanPtr, &gs) != 0) {
		goto restore;
	    }
	    dstEnd = dst + gs.bytesWrote;
	}

	/*







>
>
>
>
>
>







4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
    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
	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
		     * was found already.
		     */

		    if (eol >= dstEnd) {
			size_t offset;

			if (eol != eof) {
			    offset = eol - objPtr->bytes;
			    dst = dstEnd;
			    if (FilterInputBytes(chanPtr, &gs) != 0) {
				goto restore;
			    }







|




|







4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
	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 beginning of the next buffer, unless EOF char
		     * was found already.
		     */

		    if (eol >= dstEnd) {
			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
		}
	    }
	    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];







<







4767
4768
4769
4770
4771
4772
4773

4774
4775
4776
4777
4778
4779
4780
		}
	    }
	    break;
	case TCL_TRANSLATE_AUTO:
	    eol = dst;
	    skip = 1;
	    if (GotFlag(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
			    goto gotEOL;
			}
		    }
		    if (*eol == '\n') {
			skip++;
		    }
		    eol--;

		    goto gotEOL;
		} else if (*eol == '\n') {

		    goto gotEOL;
		}
	    }
	}
	if (eof != NULL) {
	    /*
	     * EOF character was seen. On EOF, leave current file position







>


>







4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
			    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
		 * 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);
		goto done;
	    }






















	    goto gotEOL;
	}
	dst = dstEnd;
    }

    /*
     * Found EOL or EOF, but the output buffer may now contain too many UTF-8







|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
		 * 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|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
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
     * 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)

	    || 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);






    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
 *	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.







>
















>
>
>
>
>
>

















|
|







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
     * 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_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 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
				 * 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;
    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 = TclGetByteArrayFromObj(objPtr, &byteLen);



    oldFlags = statePtr->inputEncodingFlags;
    oldRemoved = BUFFER_PADDING;
    oldLength = byteLen;
    if (bufPtr != NULL) {
	oldRemoved = bufPtr->nextRemoved;
    }








|

















>
|
>
>
>







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
				 * 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;
    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);
    if (byteArray == NULL) {
	Tcl_SetErrno(EILSEQ);
	return -1;
    }
    oldFlags = statePtr->inputEncodingFlags;
    oldRemoved = BUFFER_PADDING;
    oldLength = byteLen;
    if (bufPtr != NULL) {
	oldRemoved = bufPtr->nextRemoved;
    }

5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
	}
	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.
		 */

		byteArray = Tcl_SetByteArrayLength(objPtr, oldLength);
		CommonGetsCleanup(chanPtr);
		copiedTotal = -1;
		ResetFlag(statePtr, CHANNEL_BLOCKED);
		goto done;







|







5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
	}
	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 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
    bufPtr->nextRemoved += rawLen + skip;

    /*
     * Convert the buffer if there was an encoding.
     * XXX - unimplemented.
     */

    if (statePtr->encoding != NULL) {
    }

    /*
     * Recycle all the emptied buffers.
     */

    CommonGetsCleanup(chanPtr);







|







5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
    bufPtr->nextRemoved += rawLen + skip;

    /*
     * Convert the buffer if there was an encoding.
     * XXX - unimplemented.
     */

    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
 * Results:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static void
FreeBinaryEncoding(
    TCL_UNUSED(ClientData))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->binaryEncoding != NULL) {
	Tcl_FreeEncoding(tsdPtr->binaryEncoding);
	tsdPtr->binaryEncoding = NULL;
    }
}

static Tcl_Encoding
GetBinaryEncoding()
{
    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;
}








|
<










|





<







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
 * Results:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

static void
FreeBinaryEncoding(void)

{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->binaryEncoding != NULL) {
	Tcl_FreeEncoding(tsdPtr->binaryEncoding);
	tsdPtr->binaryEncoding = NULL;
    }
}

static Tcl_Encoding
GetBinaryEncoding(void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->binaryEncoding == NULL) {
	tsdPtr->binaryEncoding = Tcl_GetEncoding(NULL, "iso8859-1");

    }
    if (tsdPtr->binaryEncoding == NULL) {
	Tcl_Panic("binary encoding is not available");
    }
    return tsdPtr->binaryEncoding;
}

5342
5343
5344
5345
5346
5347
5348

5349
5350
5351
5352







5353
5354
5355
5356
5357
5358
5359
	    }
	}
	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);








    /*
     * Make sure that if we go through 'gets', that we reset the
     * TCL_ENCODING_START flag still. [Bug #523988]
     */

    statePtr->inputEncodingFlags &= ~TCL_ENCODING_START;







>




>
>
>
>
>
>
>







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
	    }
	}
	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;
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
 *	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
 *	retrieve the error code for the error that occurred.
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *----------------------------------------------------------------------
 */

size_t
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. */
{
    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 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
 *	retrieve the error code for the error that occurred.
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *----------------------------------------------------------------------
 */

size_t
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. */
{
    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;
    }

    /*
     * First read bytes from the push-back buffers.
     */

    while (chanPtr->inQueueHead && bytesToRead > 0) {







|








|



|












|


















|








|



|








|







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
 *	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 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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_Read(
    Tcl_Channel chan,		/* The channel from which to read. */
    char *dst,			/* Where to store input 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_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 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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_ReadRaw(
    Tcl_Channel chan,		/* The channel from which to read. */
    char *readBuf,		/* Where to store input 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_INDEX_NONE;
    }

    /*
     * First read bytes from the push-back buffers.
     */

    while (chanPtr->inQueueHead && bytesToRead > 0) {
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
	    }
	    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
     * may not be a permanent condition in the driver, and in that case we
     * have to synchronize.
     */

    if (copied) {
	return copied;
    }







|







5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
	    }
	    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 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
	     */

	    if (!GotFlag(statePtr, CHANNEL_BLOCKED) || copied == 0) {
		copied = -1;
	    }
	} else if (nread > 0) {
	    /*
             * Successful read (short is OK) - add to bytes copied.
             */

	    copied += nread;
	} else {
	    /*
	     * nread == 0.  Driver is at EOF. Let that state filter up.
	     */
	}







|
|







5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
	     */

	    if (!GotFlag(statePtr, CHANNEL_BLOCKED) || copied == 0) {
		copied = -1;
	    }
	} else if (nread > 0) {
	    /*
	     * 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
 *	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
 *	retrieve the error code for the error that occurred.
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *---------------------------------------------------------------------------
 */

size_t
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
				 * 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;







|








|



|
|







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
 *	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 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.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Size
Tcl_ReadChars(
    Tcl_Channel chan,		/* The channel to read. */
    Tcl_Obj *objPtr,		/* Input data is stored in this object. */
    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
    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 DoReadChars(chanPtr, objPtr, toRead, 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
 *	retrieve the error code for the error that occurred.
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *---------------------------------------------------------------------------
 */

static int
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
				 * 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. */
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    ChannelBuffer *bufPtr;

    int copied, copiedNow, 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 (appendFlag) {
	if (binaryMode && (NULL == TclGetBytesFromObj(NULL, objPtr, NULL))) {
	    binaryMode = 0;
	}
    } else {
	if (binaryMode) {
	    Tcl_SetByteArrayLength(objPtr, 0);
	} else {
	    Tcl_SetObjLength(objPtr, 0);

	    /*
	     * 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);
	}
    }

    /*
     * 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? */
	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? */
	UpdateInterest(chanPtr);
	return 0;
    }

    /*
     * This operation should occur at the top of a channel stack.
     */

    chanPtr = statePtr->topChanPtr;
    TclChannelPreserve((Tcl_Channel)chanPtr);

















    /*
     * 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;
	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.
	     */

	    bufPtr = statePtr->inQueueHead;
	    if (IsBufferEmpty(bufPtr)) {
		ChannelBuffer *nextPtr = bufPtr->nextPtr;

		RecycleBuffer(statePtr, bufPtr, 0);
		statePtr->inQueueHead = nextPtr;
		if (nextPtr == NULL) {
		    statePtr->inQueueTail = NULL;
		}
	    }













	}

	if (copiedNow < 0) {
	    if (GotFlag(statePtr, CHANNEL_EOF)) {
		break;
	    }
	    if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)
		    == (CHANNEL_NONBLOCKING|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;

	    toRead -= copiedNow;

	}
    }


    /*
     * 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
     * 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)

	    || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0);
    assert(!(GotFlag(statePtr, CHANNEL_EOF|CHANNEL_BLOCKED)
            == (CHANNEL_EOF|CHANNEL_BLOCKED)));
    UpdateInterest(chanPtr);












    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.
 *
 * Side effects:
 *	The storage of bytes in objPtr can cause (re-)allocation of memory.
 *
 *---------------------------------------------------------------------------
 */








|


|














|








|



|
|

>








>
|





<
|
|
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
|
|
<
<












|













|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|
|








|












>
>
>
>
>
>
>
>
>
>
>
>
>






|
|
















>
|
>



>











|
















>




>
>
>
>
>
>
>
>
>
>
>
>



















|







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
    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 TCL_INDEX_NONE;
    }

    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 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 Tcl_Size
DoReadChars(
    Channel *chanPtr,		/* The channel to read. */
    Tcl_Obj *objPtr,		/* Input data is stored in this object. */
    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 result;
    Tcl_Encoding encoding = statePtr->encoding;
    int binaryMode;
#define UTF_EXPANSION_FACTOR	1024
    int factor = UTF_EXPANSION_FACTOR;


    if (GotFlag(statePtr, CHANNEL_ENCODING_ERROR)) {
	ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_ENCODING_ERROR);
	/* TODO: UpdateInterest not needed here? */









	UpdateInterest(chanPtr);







	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: 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: 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 ; ) {
	int copiedNow = -1;
	if (statePtr->inQueueHead != NULL) {
	    if (binaryMode) {
		copiedNow = ReadBytes(statePtr, objPtr, toRead);
	    } else {
		copiedNow = ReadChars(statePtr, objPtr, toRead, &factor);
	    }

	    /*
	     * 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) || 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; /* 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 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_ENCODING_ERROR)
	    || Tcl_InputBuffered((Tcl_Channel)chanPtr) == 0);
    assert(!(GotFlag(statePtr, 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
 *	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
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.
				 * 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
				 * 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
	    : 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;
    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;




    (void) TclGetStringFromObj(objPtr, &numBytes);
    Tcl_AppendToObj(objPtr, NULL, dstLimit);
    if (toRead == srcLen) {
	size_t size;

	dst = TclGetStringStorage(objPtr, &size) + numBytes;
	dstLimit = 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







|





|










|
<





|




















>
>
>

|

|


|







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
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
				 * 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 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;

    Tcl_EncodingState savedState = statePtr->inputEncodingState;
    ChannelBuffer *bufPtr = statePtr->inQueueHead;
    int savedIEFlags = statePtr->inputEncodingFlags;
    int savedFlags = statePtr->flags;
    char *dst, *src = RemovePoint(bufPtr);
    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);
    TclAppendUtfToUtf(objPtr, NULL, dstLimit);
    if (toRead == srcLen) {
	Tcl_Size size;

	dst = TclGetStringStorage(objPtr, &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

	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);







	/*
	 * 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.
	 */







>
>
>
>
>
>







6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321

	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
		 *    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
		 * 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
		 * 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) {
		    /*







|




|







6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
		 *    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 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 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

		    statePtr->inputEncodingFlags &= ~TCL_ENCODING_START;

		    Tcl_SetObjLength(objPtr, numBytes + 1);
		    return 1;
		}

	    } else if (statePtr->flags & 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;







|







6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458

		    statePtr->inputEncodingFlags &= ~TCL_ENCODING_START;

		    Tcl_SetObjLength(objPtr, numBytes + 1);
		    return 1;
		}

	    } 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
	     *
	     * 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) {
		Tcl_Panic("Buffer Underflow, BUFFER_PADDING not enough");
	    }

	    nextPtr->nextRemoved -= srcLen;
	    memcpy(RemovePoint(nextPtr), src, srcLen);
	    RecycleBuffer(statePtr, bufPtr, 0);
	    statePtr->inQueueHead = nextPtr;







|







6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
	     *
	     * 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) {
		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
	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;

	    if (srcLen == 1) {
		/* valid src bytes end in \r */
		if (eof) {
		    *dst++ = '\r';
		    src++; srcLen--;

		} else {
		    lesser = 0;
		    break;
		}
	    } else if (src[1] == '\n') {
		*dst++ = '\n';
		src += 2; srcLen -= 2;

	    } else {
		*dst++ = '\r';
		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--; }



	    ResetFlag(statePtr, INPUT_SAW_CR);
	}
	lesser = (dstLen < srcLen) ? dstLen : srcLen;
	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;

	    if (srcLen == 0) {
		SetFlag(statePtr, INPUT_SAW_CR);
	    } else if (*src == '\n') {
		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.



	 */

	SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF);
	statePtr->inputEncodingFlags |= TCL_ENCODING_END;
	ResetFlag(statePtr, CHANNEL_BLOCKED|INPUT_SAW_CR);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * Side effects:
 *	Adds input to the input queue of a channel.
 *
 *----------------------------------------------------------------------
 */

size_t
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. */
    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;







|
>
|
>




|
>






|
>


|
>














|
|
>
>
>



|




|
>
|
>



|
>



















>
>
>




|












|







|



|







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
	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;
	    if (srcLen == 1) {
		/* valid src bytes end in \r */
		if (eof) {
		    *dst++ = '\r';
		    src++;
		    srcLen--;
		} else {
		    lesser = 0;
		    break;
		}
	    } else if (src[1] == '\n') {
		*dst++ = '\n';
		src += 2;
		srcLen -= 2;
	    } else {
		*dst++ = '\r';
		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 (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))) {
	    int numBytes = crFound - src;
	    memmove(dst, src, numBytes);

	    dst[numBytes] = '\n';
	    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--;
	    }
	    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|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_INDEX_NONE on error.
 *
 * Side effects:
 *	Adds input to the input queue of a channel.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_Ungets(
    Tcl_Channel chan,		/* The channel for which to add the input. */
    const char *str,		/* The input itself. */
    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

    /*
     * CheckChannelErrors clears too many flag bits in this one case.
     */

    flags = statePtr->flags;
    if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
	len = TCL_IO_FAILURE;
	goto done;
    }
    statePtr->flags = flags;

    /*
     * Clear the EOF flags, and clear the BLOCKED bit.
     */







|







6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826

    /*
     * CheckChannelErrors clears too many flag bits in this one case.
     */

    flags = statePtr->flags;
    if (CheckChannelErrors(statePtr, TCL_READABLE) != 0) {
	len = TCL_INDEX_NONE;
	goto done;
    }
    statePtr->flags = flags;

    /*
     * Clear the EOF flags, and clear the BLOCKED bit.
     */
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
	 * 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)) {
	    ReleaseChannelBuffer(bufPtr);
	    bufPtr = NULL;
	}

	if (bufPtr == NULL) {
	    bufPtr = AllocChannelBuffer(statePtr->bufSize);
	}
	bufPtr->nextPtr = NULL;

	toRead = SpaceLeft(bufPtr);
	assert(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);


    if (nread < 0) {
	result = Tcl_GetErrno();
    } else {
	result = 0;

	bufPtr->nextAdded += nread;
    }

    ReleaseChannelBuffer(bufPtr);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Seek --







|










|













>





>
|
|
|
|







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
	 * 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 != statePtr->bufSize + BUFFER_PADDING)) {
	    ReleaseChannelBuffer(bufPtr);
	    bufPtr = NULL;
	}

	if (bufPtr == NULL) {
	    bufPtr = AllocChannelBuffer(statePtr->bufSize);
	}
	bufPtr->nextPtr = NULL;

	toRead = SpaceLeft(bufPtr);
	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) {
	    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
 *
 * Side effects:
 *	May flush output on the channel. May discard queued input.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
Tcl_Seek(
    Tcl_Channel chan,		/* The channel on which to seek. */
    Tcl_WideInt 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. */
    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;
    }







|


|









|







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
 *
 * Side effects:
 *	May flush output on the channel. May discard queued input.
 *
 *----------------------------------------------------------------------
 */

long long
Tcl_Seek(
    Tcl_Channel chan,		/* The channel on which to seek. */
    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. */
    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
    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)
    ) {
	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.







|
<







7156
7157
7158
7159
7160
7161
7162
7163

7164
7165
7166
7167
7168
7169
7170
    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) {

	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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
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. */

    if (CheckChannelErrors(statePtr, TCL_WRITABLE | TCL_READABLE) != 0) {
	return -1;
    }

    /*
     * Disallow tell on dead channels -- channels that have been closed but







|










|







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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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. */
    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
    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)
    ) {
	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.







|
<







7320
7321
7322
7323
7324
7325
7326
7327

7328
7329
7330
7331
7332
7333
7334
    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) {

	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
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_TruncateChannel(
    Tcl_Channel chan,		/* Channel to truncate. */
    Tcl_WideInt length)		/* Length to truncate it to. */
{
    Channel *chanPtr = (Channel *) chan;
    Tcl_DriverTruncateProc *truncateProc =
	    Tcl_ChannelTruncateProc(chanPtr->typePtr);
    int result;

    if (truncateProc == NULL) {







|







7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_TruncateChannel(
    Tcl_Channel chan,		/* Channel to truncate. */
    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

	Tcl_SetErrno(EINVAL);
	return TCL_ERROR;
    }

    /*
     * Seek first to force a total flush of all pending buffers and ditch any
     * pre-read input data.
     */

    WillWrite(chanPtr);

    if (WillRead(chanPtr) == -1) {
        return TCL_ERROR;
    }







|







7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415

	Tcl_SetErrno(EINVAL);
	return TCL_ERROR;
    }

    /*
     * Seek first to force a total flush of all pending buffers and ditch any
     * preread input data.
     */

    WillWrite(chanPtr);

    if (WillRead(chanPtr) == -1) {
        return TCL_ERROR;
    }
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312

    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.
	 */

	if (statePtr->chanMsg != NULL) {
	    TclDecrRefCount(statePtr->chanMsg);
	}
	statePtr->chanMsg = statePtr->unreportedMsg;
	statePtr->unreportedMsg = NULL;







|







7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475

    if (statePtr->unreportedError != 0) {
	Tcl_SetErrno(statePtr->unreportedError);
	statePtr->unreportedError = 0;

	/*
	 * TIP #219, Tcl Channel Reflection API.
	 * 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
	return -1;
    }

    /*
     * Fail if the channel is not opened for desired operation.
     */

    if ((statePtr->flags & direction) == 0) {
	Tcl_SetErrno(EACCES);
	return -1;
    }

    /*
     * Fail if the channel is in the middle of a background copy.
     *







|







7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
	return -1;
    }

    /*
     * Fail if the channel is not opened for desired operation.
     */

    if (GotFlag(statePtr, direction) == 0) {
	Tcl_SetErrno(EACCES);
	return -1;
    }

    /*
     * Fail if the channel is in the middle of a background copy.
     *
7371
7372
7373
7374
7375
7376
7377



7378
7379
7380



























7381
7382
7383
7384
7385
7386
7387
int
Tcl_Eof(
    Tcl_Channel chan)		/* Does this channel have EOF? */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of real channel structure. */




    return GotFlag(statePtr, CHANNEL_EOF) ? 1 : 0;
}




























/*
 *----------------------------------------------------------------------
 *
 * Tcl_InputBlocked --
 *
 *	Returns 1 if input is blocked on this channel, 0 otherwise.
 *







>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
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

    for (bytesBuffered = 0, bufPtr = statePtr->inQueueHead; bufPtr != NULL;
	    bufPtr = bufPtr->nextPtr) {
	bytesBuffered += BytesLeft(bufPtr);
    }

    /*
     * Don't forget the bytes in the topmost pushback area.
     */

    for (bufPtr = statePtr->topChanPtr->inQueueHead; bufPtr != NULL;
	    bufPtr = bufPtr->nextPtr) {
	bytesBuffered += BytesLeft(bufPtr);
    }








|







7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640

    for (bytesBuffered = 0, bufPtr = statePtr->inQueueHead; bufPtr != NULL;
	    bufPtr = bufPtr->nextPtr) {
	bytesBuffered += BytesLeft(bufPtr);
    }

    /*
     * 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
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetChannelBufferSize(
    Tcl_Channel chan,		/* The channel whose buffer size to set. */
    int sz)			/* The size to set. */
{
    ChannelState *statePtr;	/* State of real channel structure. */

    /*
     * Clip the buffer size to force it into the [1,1M] range
     */








|







7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetChannelBufferSize(
    Tcl_Channel chan,		/* The channel whose buffer 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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetChannelBufferSize(
    Tcl_Channel chan)		/* The channel for which to find the buffer
				 * size. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of real channel structure. */








|







7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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
 *
 * 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
 *	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.







|







7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
 *
 * Results:
 *	TCL_ERROR.
 *
 * Side effects:

 *	An error message is generated in interp's result object to indicate
 *	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
    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";
	const char **argv;
	int argc, i;
	Tcl_DString ds;
        Tcl_Obj *errObj;

	Tcl_DStringInit(&ds);
	Tcl_DStringAppend(&ds, genericopt, -1);
	if (optionList && (*optionList)) {
	    TclDStringAppendLiteral(&ds, " ");







|

|







7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
    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 profile translation";
	const char **argv;
	Tcl_Size argc, i;
	Tcl_DString ds;
        Tcl_Obj *errObj;

	Tcl_DStringInit(&ds);
	Tcl_DStringAppend(&ds, genericopt, -1);
	if (optionList && (*optionList)) {
	    TclDStringAppendLiteral(&ds, " ");
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
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. */
    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







|







7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
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 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
	    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));
	}
	if (len > 0) {
	    return TCL_OK;
	}
    }
    if (len == 0 || HaveOpt(2, "-eofchar")) {

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-eofchar");
	}
	if (((flags & (TCL_READABLE|TCL_WRITABLE)) ==
		(TCL_READABLE|TCL_WRITABLE)) && (len == 0)) {
	    Tcl_DStringStartSublist(dsPtr);
	}
	if (flags & TCL_READABLE) {
	    if (statePtr->inEofChar == 0) {
		Tcl_DStringAppendElement(dsPtr, "");
	    } else {
		char buf[4];


		sprintf(buf, "%c", statePtr->inEofChar);
		Tcl_DStringAppendElement(dsPtr, buf);
	    }
	}
	if (flags & TCL_WRITABLE) {
	    if (statePtr->outEofChar == 0) {
		Tcl_DStringAppendElement(dsPtr, "");
	    } else {
		char buf[4];

		sprintf(buf, "%c", statePtr->outEofChar);
		Tcl_DStringAppendElement(dsPtr, buf);
	    }
	}




	if (!(flags & (TCL_READABLE|TCL_WRITABLE))) {
	    /*
	     * Not readable or writable (e.g. server socket)
	     */

	    Tcl_DStringAppendElement(dsPtr, "");
	}
	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");







<
<
<
|
|
<





>



|
<
|

|
<
|
<
<
>
|
<
|
|
<
|
<
<
|
|
|
<
|
|
<
>
>
>
>
|
<
<
<
|
|
<
<
<
<
<







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
	    return TCL_OK;
	}
    }
    if (len == 0 || HaveOpt(2, "-encoding")) {
	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-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) && (statePtr->inEofChar != 0)) {

	    snprintf(buf, sizeof(buf), "%c", statePtr->inEofChar);
	}
	if (len > 0) {

		Tcl_DStringAppend(dsPtr, buf, -1);


	    return TCL_OK;
	}

	Tcl_DStringAppendElement(dsPtr, buf);
    }

    if (len == 0 || HaveOpt(1, "-profile")) {


	int profile;
	const char *profileName;
	if (len == 0) {

	    Tcl_DStringAppendElement(dsPtr, "-profile");
	}

	/* Note currently input and output profiles are same */
	profile = ENCODING_PROFILE_GET(statePtr->inputEncodingFlags);
	profileName = TclEncodingProfileIdToName(interp, profile);
	if (profileName == NULL) {
	    return TCL_ERROR;



	}
	Tcl_DStringAppendElement(dsPtr, profileName);





	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
    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;

    /*
     * If the channel is in the middle of a background copy, fail.
     */

    if (statePtr->csPtrR || statePtr->csPtrW) {
	if (interp) {







|
|







8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
    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. */
    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) {
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
            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;











	if (Tcl_GetInt(interp, newValue, &newBufferSize) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	Tcl_SetChannelBufferSize(chan, newBufferSize);
	return TCL_OK;
    } else if (HaveOpt(2, "-encoding")) {
	Tcl_Encoding encoding;


	if ((newValue[0] == '\0') || (strcmp(newValue, "binary") == 0)) {
	    encoding = NULL;
	} 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)
		&& !(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;

	statePtr->inputEncodingFlags = TCL_ENCODING_START;

	statePtr->outputEncodingState = NULL;
	statePtr->outputEncodingFlags = TCL_ENCODING_START;

	ResetFlag(statePtr, CHANNEL_NEED_MORE_DATA);
	UpdateInterest(chanPtr);
	return TCL_OK;
    } else if (HaveOpt(2, "-eofchar")) {
	if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	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];
	    int outValue = (int) argv[outIndex][0];

	    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;
	    }
	    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));
	    }
	    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, "-translation")) {
	const char *readMode, *writeMode;

	if (Tcl_SplitList(interp, newValue, &argc, &argv) == TCL_ERROR) {
	    return TCL_ERROR;
	}








|
>
>

>
>
>
>
>
>
>
>
|






>


|












|








>

>


>
|



|
|
<
<
<
<
<
<
|
<
|
<
|
<
<
<
<
<
<
<

|
<
<
<




|
|




















>
>
>
>
>
>
>
>
>







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
            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")) {
	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 (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 = Tcl_GetEncoding(NULL, "iso8859-1");
	} 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 != 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|CHANNEL_ENCODING_ERROR);
	UpdateInterest(chanPtr);
	return TCL_OK;
    } else if (HaveOpt(2, "-eofchar")) {
	if (!newValue[0] || (!(newValue[0] & 0x80) && (!newValue[1]
#ifndef TCL_NO_DEPRECATED






		|| !strcmp(newValue+1, " {}")

#endif

		))) {







	    if (GotFlag(statePtr, TCL_READABLE)) {
		statePtr->inEofChar = newValue[0];



	    }
	} else {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"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
		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;
	    } 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) {







|







8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
		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 = 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) {
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194

		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;
	    } 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) {







<


|







8359
8360
8361
8362
8363
8364
8365

8366
8367
8368
8369
8370
8371
8372
8373
8374
8375

		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->outputTranslation = TCL_TRANSLATE_LF;
		Tcl_FreeEncoding(statePtr->encoding);
		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) {
8446
8447
8448
8449
8450
8451
8452

8453
8454
8455
8456
8457
8458
8459

static void
UpdateInterest(
    Channel *chanPtr)		/* Channel to update. */
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */

    int mask = statePtr->interestMask;

    if (chanPtr->typePtr == NULL) {
	/* Do not update interest on a closed channel */
	return;
    }








>







8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
8638
8639
8640
8641

static void
UpdateInterest(
    Channel *chanPtr)		/* Channel to update. */
{
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */
    ChannelBuffer *bufPtr = statePtr->outQueueHead;
    int mask = statePtr->interestMask;

    if (chanPtr->typePtr == NULL) {
	/* Do not update interest on a closed channel */
	return;
    }

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
	     * 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
	&& mask & TCL_WRITABLE
	&& GotFlag(statePtr, CHANNEL_NONBLOCKING)) {






	statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
	    ChannelTimerProc,chanPtr);
    }


    ChanWatch(chanPtr, mask);
}

/*
 *----------------------------------------------------------------------
 *







>
>

|





|
|
|
>
>
>
>
>

|

<







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
	     * events too. This compiles on all platforms, and also passes the
	     * testsuite on all of them.
	     */

	    mask &= ~TCL_EXCEPTION;

	    if (!statePtr->timer) {
		TclChannelPreserve((Tcl_Channel)chanPtr);
		statePtr->timerChanPtr = chanPtr;
		statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
			ChannelTimerProc, chanPtr);
	    }
	}
    }

    if (!statePtr->timer
	    && (mask & TCL_WRITABLE)
	    && GotFlag(statePtr, CHANNEL_NONBLOCKING)
	    && bufPtr
		&& !IsBufferEmpty(bufPtr)
		&& !IsBufferFull(bufPtr)
    ) {
	TclChannelPreserve((Tcl_Channel)chanPtr);
	statePtr->timerChanPtr = chanPtr;
	statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
		ChannelTimerProc,chanPtr);
    }


    ChanWatch(chanPtr, mask);
}

/*
 *----------------------------------------------------------------------
 *
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
 *	May invoke channel handlers.
 *
 *----------------------------------------------------------------------
 */

static void
ChannelTimerProc(
    ClientData clientData)
{
    Channel *chanPtr = (Channel *)clientData;

    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */









    Tcl_Preserve(statePtr);





















































    statePtr->timer = NULL;
    if (statePtr->interestMask & TCL_WRITABLE
	&& 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,
                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.
	 */

	statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
                ChannelTimerProc,chanPtr);
	Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE);
    } else {
	UpdateInterest(chanPtr);
    }
    Tcl_Release(statePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateChannelHandler --
 *







|


>

|
>
>
>
>
>

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
 *	May invoke channel handlers.
 *
 *----------------------------------------------------------------------
 */

static void
ChannelTimerProc(
    void *clientData)
{
    Channel *chanPtr = (Channel *)clientData;
    /* State info for channel */
    ChannelState *statePtr = chanPtr->state;

    /* TclChannelPreserve() must be called before the current function was
     * scheduled, is already in effect.  In this function it guards against
     * deallocation in Tcl_NotifyChannel and also keps the channel preserved
     * until ChannelTimerProc is later called again.
     */

    if (chanPtr->typePtr == NULL) {
	CleanupTimerHandler(statePtr);
    } else {
	Tcl_Preserve(statePtr);
	statePtr->timer = NULL;
	if (statePtr->interestMask & TCL_WRITABLE
		&& 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,
		ChannelTimerProc,chanPtr);
	    Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_WRITABLE);
	} else {
	    /* The channel may have just been closed from within Tcl_NotifyChannel */
	    if (!GotFlag(statePtr, CHANNEL_INCLOSE)) {
		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 {
		    CleanupTimerHandler(statePtr);
		    UpdateInterest(chanPtr);
		}
	    } else {
		CleanupTimerHandler(statePtr);
	    }
	}
	Tcl_Release(statePtr);
    }
}

static void
DeleteTimerHandler(
    ChannelState *statePtr
)
{
    if (statePtr->timer != NULL) {
	Tcl_DeleteTimerHandler(statePtr->timer);
	CleanupTimerHandler(statePtr);
    }
}
static void
CleanupTimerHandler(
    ChannelState *statePtr
){
    TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr);
    statePtr->timer = NULL;












    statePtr->timerChanPtr = NULL;
















}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateChannelHandler --
 *
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
    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. */
{
    ChannelHandler *chPtr;
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */

    /*







|







8845
8846
8847
8848
8849
8850
8851
8852
8853
8854
8855
8856
8857
8858
8859
    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. */
    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
	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.
     */

    chPtr->mask = mask;

    /*
     * Recompute the interest mask for the channel - this call may actually be
     * disabling an existing handler.







|







8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
	chPtr->chanPtr = chanPtr;
	chPtr->nextPtr = statePtr->chPtr;
	statePtr->chPtr = chPtr;
    }

    /*
     * The remainder of the initialization below is done regardless of whether
     * 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
 */

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
				 * delete. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    ChannelHandler *chPtr, *prevChPtr;
    Channel *chanPtr = (Channel *) chan;
    ChannelState *statePtr = chanPtr->state;
				/* State info for channel */







|







8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928
8929
8930
8931
 */

void
Tcl_DeleteChannelHandler(
    Tcl_Channel chan,		/* The channel for which to remove the
				 * callback. */
    Tcl_ChannelProc *proc,	/* The procedure in the callback to delete. */
    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
 *	Whatever the script does.
 *
 *----------------------------------------------------------------------
 */

void
TclChannelEventScriptInvoker(
    ClientData 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







|







9123
9124
9125
9126
9127
9128
9129
9130
9131
9132
9133
9134
9135
9136
9137
 *	Whatever the script does.
 *
 *----------------------------------------------------------------------
 */

void
TclChannelEventScriptInvoker(
    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
 *	May create a channel handler for the specified channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FileEventObjCmd(
    TCL_UNUSED(ClientData),
    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 */







|







9191
9192
9193
9194
9195
9196
9197
9198
9199
9200
9201
9202
9203
9204
9205
 *	May create a channel handler for the specified channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FileEventObjCmd(
    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 */
9001
9002
9003
9004
9005
9006
9007
9008
9009
9010
9011
9012
9013
9014
9015
    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) {
	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.







|







9223
9224
9225
9226
9227
9228
9229
9230
9231
9232
9233
9234
9235
9236
9237
    chanName = TclGetString(objv[1]);
    chan = Tcl_GetChannel(interp, chanName, NULL);
    if (chan == NULL) {
	return TCL_ERROR;
    }
    chanPtr = (Channel *) chan;
    statePtr = chanPtr->state;
    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
 *	Calls CopyData for -command invocation.
 *
 *----------------------------------------------------------------------
 */

static void
ZeroTransferTimerProc(
    ClientData clientData)
{
    /* calling CopyData with mask==0 still implies immediate invocation of the
     *  -command callback, and completion of the fcopy.
     */
    CopyData((CopyState *)clientData, 0);
}








|







9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
 *	Calls CopyData for -command invocation.
 *
 *----------------------------------------------------------------------
 */

static void
ZeroTransferTimerProc(
    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
 */

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. */
    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;







|







9319
9320
9321
9322
9323
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
 */

int
TclCopyChannel(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Channel inChan,		/* Channel to read from. */
    Tcl_Channel outChan,	/* Channel to write to. */
    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;
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
	return TCL_ERROR;
    }

    /*
     * Make sure the output side is unbuffered.
     */

    outStatePtr->flags = (outStatePtr->flags & ~CHANNEL_LINEBUFFERED)
	    | 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 = 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->bufSize = !moveBytes * inStatePtr->bufSize;
    csPtr->readPtr = inPtr;
    csPtr->writePtr = outPtr;
    csPtr->readFlags = readFlags;
    csPtr->writeFlags = writeFlags;
    csPtr->toRead = toRead;
    csPtr->total = (Tcl_WideInt) 0;







|
|

<
<
<
<
<
|
<
<
<
<







|







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
	return TCL_ERROR;
    }

    /*
     * Make sure the output side is unbuffered.
     */

    ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED);
    SetFlag(outStatePtr, CHANNEL_UNBUFFERED);






    moveBytes = Lossless(inStatePtr, outStatePtr, toRead);





    /*
     * 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(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize);
    csPtr->bufSize = !moveBytes * inStatePtr->bufSize;
    csPtr->readPtr = inPtr;
    csPtr->writePtr = outPtr;
    csPtr->readFlags = readFlags;
    csPtr->writeFlags = writeFlags;
    csPtr->toRead = toRead;
    csPtr->total = (Tcl_WideInt) 0;
9285
9286
9287
9288
9289
9290
9291
9292
9293
9294
9295
9296
9297
9298
9299
	Tcl_SetObjResult(csPtr->interp, errObj);
	StopCopy(csPtr);
    }
}

static void
MBEvent(
    ClientData 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;








|







9498
9499
9500
9501
9502
9503
9504
9505
9506
9507
9508
9509
9510
9511
9512
	Tcl_SetObjResult(csPtr->interp, errObj);
	StopCopy(csPtr);
    }
}

static void
MBEvent(
    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
	}
	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.
         */

	bufPtr = AllocChannelBuffer(extra);

	tail->nextAdded -= extra;
	memcpy(InsertPoint(bufPtr), InsertPoint(tail), extra);
	bufPtr->nextAdded += extra;
	bufPtr->nextPtr = tail->nextPtr;







|
|
|
|
|
|
|







9577
9578
9579
9580
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
	}
	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 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
    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;

    Tcl_WideInt total;

    const char *buffer;
    int inBinary, outBinary, sameEncoding;
				/* Encoding control */
    int underflow;		/* Input underflow */

    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);
    outBinary = (outStatePtr->encoding == NULL);
    sameEncoding = (inStatePtr->encoding == outStatePtr->encoding);

    if (!(inBinary || sameEncoding)) {
	TclNewObj(bufObj);
	Tcl_IncrRefCount(bufObj);
    }

    while (csPtr->toRead != (Tcl_WideInt) 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;




	}
	Tcl_GetChannelError(outChan, &msg);
	if ((outStatePtr->unreportedError != 0) || (msg != NULL)) {
	    Tcl_SetErrno(outStatePtr->unreportedError);
	    outStatePtr->unreportedError = 0;




	    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.
	     */

	    if ((csPtr->toRead == (Tcl_WideInt) -1)
                    || (csPtr->toRead > (Tcl_WideInt) csPtr->bufSize)) {
		sizeb = csPtr->bufSize;
	    } else {
		sizeb = csPtr->toRead;
	    }

	    if (inBinary || sameEncoding) {
		size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb,
                              !GotFlag(inStatePtr, CHANNEL_NONBLOCKING));
	    } else {
		size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb,

			0 /* No append */);















	    }


	    underflow = (size >= 0) && ((size_t)size < sizeb);	/* Input underflow */
	}

	if (size < 0) {
	readError:
	    if (interp) {
		TclNewObj(errObj);
		Tcl_AppendStringsToObj(errObj, "error reading \"",
			Tcl_GetChannelName(inChan), "\": ", NULL);
		if (msg != NULL) {
		    Tcl_AppendObjToObj(errObj, msg);
		} else {
		    Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp),
			    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 (mask & TCL_WRITABLE) {
		    Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr);
		}
		Tcl_CreateChannelHandler(inChan, TCL_READABLE, CopyEventProc,
			csPtr);
	    }
	    if (size == 0) {







|
|
>

>

|
<

















|
<
<

|














>
>
>
>





>
>
>
>













|









|




>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|







|




|

















|
|







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
    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;
    Tcl_Size sizeb;
    Tcl_Size sizePart;
    Tcl_WideInt total;
    Tcl_WideInt size;
    const char *buffer;
    int moveBytes;

    int underflow;		/* Input underflow */

    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.
     */

    moveBytes = Lossless(inStatePtr, outStatePtr, csPtr->toRead);



    if (!moveBytes) {
	TclNewObj(bufObj);
	Tcl_IncrRefCount(bufObj);
    }

    while (csPtr->toRead != (Tcl_WideInt) 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 characters.
	     */

	    if ((csPtr->toRead == (Tcl_WideInt) -1)
                    || (csPtr->toRead > (Tcl_WideInt) csPtr->bufSize)) {
		sizeb = csPtr->bufSize;
	    } else {
		sizeb = csPtr->toRead;
	    }

	    if (moveBytes) {
		size = DoRead(inStatePtr->topChanPtr, csPtr->buffer, sizeb,
                              !GotFlag(inStatePtr, CHANNEL_NONBLOCKING));
	    } else {
		size = DoReadChars(inStatePtr->topChanPtr, bufObj, sizeb,
			!GotFlag(inStatePtr, CHANNEL_NONBLOCKING)
			,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), "\": ", (char *)NULL);
		if (msg != NULL) {
		    Tcl_AppendObjToObj(errObj, msg);
		} else {
		    Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp),
			    (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 (mask & TCL_WRITABLE) {
		    Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr);
		}
		Tcl_CreateChannelHandler(inChan, TCL_READABLE, CopyEventProc,
			csPtr);
	    }
	    if (size == 0) {
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
	    }
	}

	/*
	 * Now write the buffer out.
	 */

	if (inBinary || sameEncoding) {
	    buffer = csPtr->buffer;
	    sizeb = 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
	 * 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
	 * 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) {
	writeError:
	    if (interp) {
		TclNewObj(errObj);
		Tcl_AppendStringsToObj(errObj, "error writing \"",
			Tcl_GetChannelName(outChan), "\": ", NULL);
		if (msg != NULL) {
		    Tcl_AppendObjToObj(errObj, msg);
		} else {
		    Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp),
			    NULL);
		}
	    }
	    if (msg != NULL) {
		Tcl_DecrRefCount(msg);
	    }
	    break;
	}

	/*
	 * Update the current byte 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.
	 */

	if (csPtr->toRead != -1) {
	    csPtr->toRead -= size;
	}
	csPtr->total += size;








|

|


<
<
<
<
<





|


|






|




|




|









|


|







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
	    }
	}

	/*
	 * Now write the buffer out.
	 */

	if (moveBytes) {
	    buffer = csPtr->buffer;
	    sizeb = WriteBytes(outStatePtr->topChanPtr, buffer, size);
	} else {
	    buffer = TclGetStringFromObj(bufObj, &sizeb);





	    sizeb = WriteChars(outStatePtr->topChanPtr, buffer, sizeb);
	}

	/*
	 * [Bug 2895565]. At this point 'size' still contains the number of
	 * 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
	 * 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 < 0) {
	writeError:
	    if (interp) {
		TclNewObj(errObj);
		Tcl_AppendStringsToObj(errObj, "error writing \"",
			Tcl_GetChannelName(outChan), "\": ", (char *)NULL);
		if (msg != NULL) {
		    Tcl_AppendObjToObj(errObj, msg);
		} else {
		    Tcl_AppendStringsToObj(errObj, Tcl_PosixError(interp),
			    (char *)NULL);
		}
	    }
	    if (msg != NULL) {
		Tcl_DecrRefCount(msg);
	    }
	    break;
	}

	/*
	 * 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 characters left to copy.
	 */

	if (csPtr->toRead != -1) {
	    csPtr->toRead -= size;
	}
	csPtr->total += size;

9719
9720
9721
9722
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732
9733
9734

    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.
     */

    total = csPtr->total;
    if (cmdPtr && interp) {
	int code;

	/*







|
|







9952
9953
9954
9955
9956
9957
9958
9959
9960
9961
9962
9963
9964
9965
9966
9967

    if (bufObj != NULL) {
	TclDecrRefCount(bufObj);
	bufObj = NULL;
    }

    /*
     * 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;

	/*
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
 *	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
 *	that occurred.
 *
 *	The number of bytes stored can be less than the number
 * 	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)
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *----------------------------------------------------------------------
 */

static int
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. */
    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_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);







|








|







|



|

















>
>
>
>
>







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
 *	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 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
 *	  - 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 TCL_INDEX_NONE)
 *
 * Side effects:
 *	May cause input to be buffered.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Size
DoRead(
    Channel *chanPtr,		/* The channel from which to read. */
    char *dst,			/* Where to store input 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);
9856
9857
9858
9859
9860
9861
9862
9863
9864
9865
9866
9867
9868
9869
9870

	/*
	 * 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))) {
						/* Not enough bytes in it yet
						 * to fill the dst */
	    int code;

	moreData:
	    code = GetInput(chanPtr);
	    bufPtr = statePtr->inQueueHead;







|







10094
10095
10096
10097
10098
10099
10100
10101
10102
10103
10104
10105
10106
10107
10108

	/*
	 * 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 */
		((Tcl_Size) BytesLeft(bufPtr) < bytesToRead))) {
						/* Not enough bytes in it yet
						 * to fill the dst */
	    int code;

	moreData:
	    code = GetInput(chanPtr);
	    bufPtr = statePtr->inQueueHead;
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
	     */

	    if (bytesToRead == 0) {
		break;
	    }

	    /*
	     * 1) We're @EOF because we saw eof char.
	     */

	    if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) {
		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) {
		    /*
		     * ...and there never will be.
		     */

		    *p++ = '\r';
		    bytesToRead--;
		    bufPtr->nextRemoved++;
		} else if (statePtr->flags & CHANNEL_BLOCKED) {
		    /*
		     * ...and we cannot get more now.
		     */

		    SetFlag(statePtr, CHANNEL_NEED_MORE_DATA);
		    break;
		} else {







|


|

















|







|







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
	     */

	    if (bytesToRead == 0) {
		break;
	    }

	    /*
	     * 1) We're @EOF because we saw eof char, or there was an encoding error.
	     */

	    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 (GotFlag(statePtr, CHANNEL_EOF)) {
		    /*
		     * ...and there never will be.
		     */

		    *p++ = '\r';
		    bytesToRead--;
		    bufPtr->nextRemoved++;
		} else if (GotFlag(statePtr, CHANNEL_BLOCKED)) {
		    /*
		     * ...and we cannot get more now.
		     */

		    SetFlag(statePtr, CHANNEL_NEED_MORE_DATA);
		    break;
		} else {
10000
10001
10002
10003
10004
10005
10006

10007
10008
10009
10010
10011
10012
10013
10014
10015
10016
10017
10018
10019
    }
    if (bytesToRead == 0) {
	ResetFlag(statePtr, CHANNEL_BLOCKED);
    }

    assert(!GotFlag(statePtr, CHANNEL_EOF)
	    || GotFlag(statePtr, CHANNEL_STICKY_EOF)

	    || 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);
}

/*
 *----------------------------------------------------------------------
 *
 * CopyEventProc --
 *







>





|







10238
10239
10240
10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
10253
10254
10255
10256
10257
10258
    }
    if (bytesToRead == 0) {
	ResetFlag(statePtr, CHANNEL_BLOCKED);
    }

    assert(!GotFlag(statePtr, CHANNEL_EOF)
	    || GotFlag(statePtr, CHANNEL_STICKY_EOF)
	    || GotFlag(statePtr, 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 (Tcl_Size)(p - dst);
}

/*
 *----------------------------------------------------------------------
 *
 * CopyEventProc --
 *
10028
10029
10030
10031
10032
10033
10034
10035
10036
10037
10038
10039








































10040
10041
10042
10043
10044
10045
10046
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
CopyEventProc(
    ClientData clientData,
    int mask)
{
    (void) CopyData((CopyState *)clientData, mask);
}









































/*
 *----------------------------------------------------------------------
 *
 * StopCopy --
 *
 *	This routine halts a copy that is in progress.







|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
CopyEventProc(
    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
    outStatePtr = csPtr->writePtr->state;

    /*
     * Restore the old blocking mode and output buffering mode.
     */

    nonBlocking = csPtr->readFlags & CHANNEL_NONBLOCKING;
    if (nonBlocking != (inStatePtr->flags & 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)) {
	    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);

    if (csPtr->cmdPtr) {
	Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr);
	if (inChan != outChan) {
	    Tcl_DeleteChannelHandler(outChan, CopyEventProc, csPtr);
	}
	Tcl_DeleteChannelHandler(inChan, MBEvent, csPtr);







|





|





|
|







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
    outStatePtr = csPtr->writePtr->state;

    /*
     * Restore the old blocking mode and output buffering mode.
     */

    nonBlocking = csPtr->readFlags & 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 != GotFlag(outStatePtr, CHANNEL_NONBLOCKING)) {
	    SetBlockMode(NULL, csPtr->writePtr,
		    nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING);
	}
    }
    ResetFlag(outStatePtr, 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);
10402
10403
10404
10405
10406
10407
10408
10409
10410
10411
10412
10413
10414
10415
10416
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);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IsChannelExisting --
 *







|







10681
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693
10694
10695
int
Tcl_IsChannelShared(
    Tcl_Channel chan)		/* The channel to query */
{
    ChannelState *statePtr = ((Channel *) chan)->state;
				/* State of real channel structure. */

    return ((statePtr->refCount > 1) ? 1 : 0);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_IsChannelExisting --
 *
10812
10813
10814
10815
10816
10817
10818
10819
10820
10821
10822
10823
10824
10825
10826
10827






10828
10829
10830
10831
10832
10833
10834

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;
    }

    if (msg != NULL) {
	iPtr->chanMsg = FixLevelCode(msg);
	Tcl_IncrRefCount(iPtr->chanMsg);






    }
    return;
}

/*
 *----------------------------------------------------------------------
 *







<
<
<
|
<




>
>
>
>
>
>







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

void
Tcl_SetChannelErrorInterp(
    Tcl_Interp *interp,		/* Interp to store the data into. */
    Tcl_Obj *msg)		/* Error message to store. */
{
    Interp *iPtr = (Interp *) interp;



    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;
}

/*
 *----------------------------------------------------------------------
 *
10848
10849
10850
10851
10852
10853
10854
10855
10856
10857
10858
10859
10860
10861
10862
10863






10864
10865
10866
10867
10868
10869
10870

void
Tcl_SetChannelError(
    Tcl_Channel chan,		/* Channel to store the data into. */
    Tcl_Obj *msg)		/* Error message to store. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;

    if (statePtr->chanMsg != NULL) {
	TclDecrRefCount(statePtr->chanMsg);
	statePtr->chanMsg = NULL;
    }

    if (msg != NULL) {
	statePtr->chanMsg = FixLevelCode(msg);
	Tcl_IncrRefCount(statePtr->chanMsg);






    }
    return;
}

/*
 *----------------------------------------------------------------------
 *







<
<
<
|
<




>
>
>
>
>
>







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

void
Tcl_SetChannelError(
    Tcl_Channel chan,		/* Channel to store the data into. */
    Tcl_Obj *msg)		/* Error message to store. */
{
    ChannelState *statePtr = ((Channel *) chan)->state;



    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
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
FixLevelCode(
    Tcl_Obj *msg)
{
    int explicitResult, numOptions, lc, lcn;

    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
     * information. Hence an error means that we've got serious breakage.
     */

    res = Tcl_ListObjGetElements(NULL, msg, &lc, &lv);
    if (res != TCL_OK) {
	Tcl_Panic("Tcl_SetChannelError: bad syntax of message");
    }

    explicitResult = (1 == (lc % 2));
    numOptions = lc - explicitResult;








|
>












|



|







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
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
FixLevelCode(
    Tcl_Obj *msg)
{
    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 marshal the
     * information. Hence an error means that we've got serious breakage.
     */

    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
    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
     * 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")) {







|
|







11250
11251
11252
11253
11254
11255
11256
11257
11258
11259
11260
11261
11262
11263
11264
11265
    if (newcode >= 0) {
	lcn += 2;
    }

    lvn = (Tcl_Obj **)Tcl_Alloc(lcn * sizeof(Tcl_Obj *));

    /*
     * 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
{
    return chanTypePtr->truncateProc;
}

/*
 *----------------------------------------------------------------------
 *
 * DupChannelIntRep --
 *
 *	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(
    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);
    assert(resPtr);
    ChanSetIntRep(copyPtr, resPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeChannelIntRep --
 *
 *	Release statePtr storage.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May cause state to be freed.
 *
 *----------------------------------------------------------------------
 */

static void
FreeChannelIntRep(
    Tcl_Obj *objPtr)		/* Object with internal rep to free. */
{
    ResolvedChanName *resPtr;

    ChanGetIntRep(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;


#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('B', CHANNEL_BLOCKED);
    ChanFlag('/', INPUT_SAW_CR);
    ChanFlag('D', CHANNEL_DEAD);
    ChanFlag('R', CHANNEL_RAW_MODE);
    ChanFlag('x', CHANNEL_INCLOSE);

    buf[i] ='\0';







|















|







|

|





|













|




|



















<

>












>







11388
11389
11390
11391
11392
11393
11394
11395
11396
11397
11398
11399
11400
11401
11402
11403
11404
11405
11406
11407
11408
11409
11410
11411
11412
11413
11414
11415
11416
11417
11418
11419
11420
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
{
    return chanTypePtr->truncateProc;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
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;

    ChanGetInternalRep(srcPtr, resPtr);
    assert(resPtr);
    ChanSetInternalRep(copyPtr, resPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeChannelInternalRep --
 *
 *	Release statePtr storage.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	May cause state to be freed.
 *
 *----------------------------------------------------------------------
 */

static void
FreeChannelInternalRep(
    Tcl_Obj *objPtr)		/* Object with internal rep to free. */
{
    ResolvedChanName *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)
{

    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
/*
 * 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
				 * will be put in the buffer. */
    int nextRemoved;		/* Position of next byte to be removed from
				 * the buffer. */
    int 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
				 * bytes. This must be the last field in the
				 * structure. */
} ChannelBuffer;

#define CHANNELBUFFER_HEADER_SIZE	offsetof(ChannelBuffer, buf)

/*







|
|

|

|



|







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 {
    Tcl_Size refCount;		/* Current uses count */
    Tcl_Size nextAdded;		/* The next position into which a character
				 * will be put in the buffer. */
    Tcl_Size nextRemoved;		/* Position of next byte to be removed from
				 * 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 occupies this space + bufSize-1
				 * bytes. This must be the last field in the
				 * structure. */
} ChannelBuffer;

#define CHANNELBUFFER_HEADER_SIZE	offsetof(ChannelBuffer, buf)

/*
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
     * 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;
} 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
				 * 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. */







|















|







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
     * 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. */

    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;			/* 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
				/* 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. */

    int outEofChar;		/* If nonzero, append this to the channel when
				 * it is closed if it is open for writing. */

    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
				 * 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. */







>

|
>



|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
				/* 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. 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. */
    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
    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_TimerToken timer;	/* Handle to wakeup timer for this channel. */



    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.
     */

    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
				 * lookup results. */


} ChannelState;

/*
 * Values for the flags field in Channel. Any ORed 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
					 * 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







|

>
>
>


















|









>
>



|





|

<
<
<
<







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236




237
238
239
240
241
242
243
    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. */
    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.
     */

    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
				 * lookup results. */
    int maxPerms;		/* TIP #220: Max access privileges
				 * the channel was created with. */
} ChannelState;

/*
 * 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<<6)	/* Channel is currently in nonblocking
					 * mode. */




#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
					 * 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_RAW_MODE	(1<<16)	/* When set, notes that the Raw API is
					 * being used. */




#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







>
>


|
>
>
>







268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
					 * 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
/*
 * tclIOCmd.c --
 *
 *	Contains the definitions of most of the Tcl commands relating to IO.
 *
 * Copyright (c) 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"



/*
 * Callback structure for accept callback in a TCP server.
 */

typedef struct {
    Tcl_Obj *script;		/* Script to invoke. */





|






>
>







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 © 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. */
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 * Static functions for this file:
 */

static Tcl_ExitProc		FinalizeIOCmdTSD;
static Tcl_TcpAcceptProc 	AcceptCallbackProc;
static Tcl_ObjCmdProc		ChanPendingObjCmd;
static Tcl_ObjCmdProc		ChanTruncateObjCmd;
static void			RegisterTcpServerInterpCleanup(
				    Tcl_Interp *interp,
				    AcceptCallback *acceptCallbackPtr);
static Tcl_InterpDeleteProc	TcpAcceptCallbacksDeleteProc;
static void		TcpServerCloseProc(ClientData callbackData);
static void		UnregisterTcpServerInterpCleanupProc(
			    Tcl_Interp *interp,
			    AcceptCallback *acceptCallbackPtr);

/*
 *----------------------------------------------------------------------
 *







|
|
|

|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 * Static functions for this file:
 */

static Tcl_ExitProc		FinalizeIOCmdTSD;
static Tcl_TcpAcceptProc 	AcceptCallbackProc;
static Tcl_ObjCmdProc		ChanPendingObjCmd;
static Tcl_ObjCmdProc		ChanTruncateObjCmd;
static void		RegisterTcpServerInterpCleanup(
			    Tcl_Interp *interp,
			    AcceptCallback *acceptCallbackPtr);
static Tcl_InterpDeleteProc	TcpAcceptCallbacksDeleteProc;
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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
FinalizeIOCmdTSD(
    TCL_UNUSED(ClientData))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (tsdPtr->stdoutObjPtr != NULL) {
	Tcl_DecrRefCount(tsdPtr->stdoutObjPtr);
	tsdPtr->stdoutObjPtr = NULL;
    }







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
FinalizeIOCmdTSD(
    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
 *	Produces output on a channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PutsObjCmd(
    TCL_UNUSED(ClientData),
    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. */
    int mode;			/* Mode in which channel is opened. */

    switch (objc) {
    case 2:			/* [puts $x] */
	string = objv[1];
	newline = 1;
	break;







|








|







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(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? */
    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;
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
		"channel \"%s\" wasn't opened for writing",
		TclGetString(chanObjPtr)));
	return TCL_ERROR;
    }

    TclChannelPreserve(chan);
    result = Tcl_WriteObj(chan, string);
    if (result == -1) {
	goto error;
    }
    if (newline != 0) {
	result = Tcl_WriteChars(chan, "\n", 1);
	if (result == -1) {
	    goto error;
	}
    }
    TclChannelRelease(chan);
    return TCL_OK;

    /*







|




|







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 == TCL_INDEX_NONE) {
	goto error;
    }
    if (newline != 0) {
	result = Tcl_WriteChars(chan, "\n", 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
 *	May cause output to appear on the specified channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FlushObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
 *	May cause output to appear on the specified channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FlushObjCmd(
    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;
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
 *	May consume input from channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetsObjCmd(
    TCL_UNUSED(ClientData),
    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. */
    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?");
	return TCL_ERROR;







|





|







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
 *	May consume input from channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_GetsObjCmd(
    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. */
    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?");
	return TCL_ERROR;
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
		TclGetString(chanObjPtr)));
	return TCL_ERROR;
    }

    TclChannelPreserve(chan);
    TclNewObj(linePtr);
    lineLen = Tcl_GetsObj(chan, linePtr);
    if (lineLen < 0) {
	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;
    }
    if (objc == 3) {
	if (Tcl_ObjSetVar2(interp, objv[2], NULL, linePtr,
		TCL_LEAVE_ERR_MSG) == NULL) {
	    code = TCL_ERROR;
	    goto done;
	}


	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(lineLen));
    } else {
	Tcl_SetObjResult(interp, linePtr);
    }
  done:
    TclChannelRelease(chan);
    return code;
}







|


















|







>
>
|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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
		TclGetString(chanObjPtr)));
	return TCL_ERROR;
    }

    TclChannelPreserve(chan);
    TclNewObj(linePtr);
    lineLen = Tcl_GetsObj(chan, linePtr);
    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 = 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, 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
 *	May consume input from channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ReadObjCmd(
    TCL_UNUSED(ClientData),
    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? */
    int mode;			/* Mode in which channel is opened. */
    Tcl_Obj *resultPtr, *chanObjPtr;

    if ((objc != 2) && (objc != 3)) {
	Interp *iPtr;

    argerror:







|






|
|







358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
 *	May consume input from channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ReadObjCmd(
    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? */
    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:
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

    /*
     * Compute how many bytes to read.
     */

    toRead = -1;
    if (i < objc) {
	if ((TclGetIntFromObj(interp, 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;
	}
    }

    TclNewObj(resultPtr);
    Tcl_IncrRefCount(resultPtr);
    TclChannelPreserve(chan);
    charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 0);
    if (charactersRead < 0) {








	/*
	 * 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);


	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;

	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 --







|

|
|
|
|
|




<


|
>
>
>
>
>
>
>
>













|
>
>









|








<







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 ((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", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    TclNewObj(resultPtr);

    TclChannelPreserve(chan);
    charactersRead = Tcl_ReadChars(chan, resultPtr, toRead, 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);
	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;
	Tcl_Size length;

	result = TclGetStringFromObj(resultPtr, &length);
	if (result[length - 1] == '\n') {
	    Tcl_SetObjLength(resultPtr, length - 1);
	}
    }
    Tcl_SetObjResult(interp, resultPtr);
    TclChannelRelease(chan);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SeekObjCmd --
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
 *	flush queued output.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SeekObjCmd(
    TCL_UNUSED(ClientData),
    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? */







|







495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
 *	flush queued output.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SeekObjCmd(
    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? */
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId 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) {
	return TCL_ERROR;
    }
    mode = SEEK_SET;
    if (objc == 4) {
	if (Tcl_GetIndexFromObj(interp, objv[3], originOptions, "origin", 0,
		&optionIndex) != TCL_OK) {
	    return TCL_ERROR;







|







517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
    if ((objc != 3) && (objc != 4)) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId offset ?origin?");
	return TCL_ERROR;
    }
    if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
	return TCL_ERROR;
    }
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TellObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_TellObjCmd(
    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;
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
 *	May discard queued input; may flush queued output.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_CloseObjCmd(
    TCL_UNUSED(ClientData),
    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







|







632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
 *	May discard queued input; may flush queued output.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_CloseObjCmd(
    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
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
	 * 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;

	if (Tcl_IsShared(resultPtr)) {
	    resultPtr = Tcl_DuplicateObj(resultPtr);
	    Tcl_SetObjResult(interp, resultPtr);
	}
	string = TclGetStringFromObj(resultPtr, &len);
	if ((len > 0) && (string[len - 1] == '\n')) {







|







705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
	 * 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;
	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
 *	May modify the behavior of an IO channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FconfigureObjCmd(
    TCL_UNUSED(ClientData),
    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. */







|







740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
 *	May modify the behavior of an IO channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FconfigureObjCmd(
    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. */
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
 *	specified channel has an EOF condition.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_EofObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;

    if (objc != 2) {







|







815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
 *	specified channel has an EOF condition.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_EofObjCmd(
    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) {
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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExecObjCmd(
    TCL_UNUSED(ClientData),
    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;
    static const char *const options[] = {
	"-ignorestderr", "-keepnewline", "--", NULL
    };
    enum execOptionsEnum {
	EXEC_IGNORESTDERR, EXEC_KEEPNEWLINE, EXEC_LAST
    };








|










|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ExecObjCmd(
    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;
    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
     */

    TclStackFree(interp, (void *) argv);

    if (chan == NULL) {
	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).
	 */








>
>
>
>
>







942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
     */

    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
 *	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.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_FblockedObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;
    int mode;








|






|







1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
 *	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
 *	preceding input operation on the channel would have blocked.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_FblockedObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;
    int mode;

1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_OpenObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_OpenObjCmd(
    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
    /*
     * Open the file or create a process pipeline.
     */

    if (!pipeline) {
	chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot);
    } else {
	int mode, seekFlag, cmdObjc, binary;

	const char **cmdArgv;

	if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) {
	    return TCL_ERROR;
	}

	mode = TclGetOpenModeEx(interp, modeString, &seekFlag, &binary);
	if (mode == -1) {
	    chan = NULL;
	} else {
	    int flags = TCL_STDERR | TCL_ENFORCE_MODE;

	    switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
	    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) {
		Tcl_SetChannelOption(interp, chan, "-translation", "binary");
	    }
	}
	Tcl_Free((void *)cmdArgv);
    }
    if (chan == NULL) {
	return TCL_ERROR;







|
>






|





|














|







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
    /*
     * Open the file or create a process pipeline.
     */

    if (!pipeline) {
	chan = Tcl_FSOpenFileChannel(interp, objv[1], modeString, prot);
    } else {
	int mode, modeFlags;
	Tcl_Size cmdObjc;
	const char **cmdArgv;

	if (Tcl_SplitList(interp, what+1, &cmdObjc, &cmdArgv) != TCL_OK) {
	    return TCL_ERROR;
	}

	mode = TclGetOpenMode(interp, modeString, &modeFlags);
	if (mode == -1) {
	    chan = NULL;
	} else {
	    int flags = TCL_STDERR | TCL_ENFORCE_MODE;

	    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 ((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
 *	subsequently to eval accept scripts.
 *
 *----------------------------------------------------------------------
 */

static void
TcpAcceptCallbacksDeleteProc(
    ClientData 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;








|







1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
 *	subsequently to eval accept scripts.
 *
 *----------------------------------------------------------------------
 */

static void
TcpAcceptCallbacksDeleteProc(
    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
    Tcl_HashEntry *hPtr;

    hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
    if (hTblPtr == NULL) {
	return;
    }

    hPtr = Tcl_FindHashEntry(hTblPtr, (char *) acceptCallbackPtr);
    if (hPtr != NULL) {
	Tcl_DeleteHashEntry(hPtr);
    }
}

/*
 *----------------------------------------------------------------------







|







1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
    Tcl_HashEntry *hPtr;

    hTblPtr = (Tcl_HashTable *)Tcl_GetAssocData(interp, "tclTCPAcceptCallbacks", NULL);
    if (hTblPtr == NULL) {
	return;
    }

    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
 *	Whatever the script does.
 *
 *----------------------------------------------------------------------
 */

static void
AcceptCallbackProc(
    ClientData 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. */
{







|







1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
 *	Whatever the script does.
 *
 *----------------------------------------------------------------------
 */

static void
AcceptCallbackProc(
    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
 *	longer be informed.
 *
 *----------------------------------------------------------------------
 */

static void
TcpServerCloseProc(
    ClientData callbackData)	/* The data passed in the call to
				 * Tcl_CreateCloseHandler. */
{
    AcceptCallback *acceptCallbackPtr = (AcceptCallback *)callbackData;
				/* The actual data. */

    if (acceptCallbackPtr->interp != NULL) {
	UnregisterTcpServerInterpCleanupProc(acceptCallbackPtr->interp,







|







1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
 *	longer be informed.
 *
 *----------------------------------------------------------------------
 */

static void
TcpServerCloseProc(
    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
 *	Creates a socket based channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SocketObjCmd(
    TCL_UNUSED(ClientData),
    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
    };
    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;
    unsigned int flags = 0;
    const char *host, *port, *myaddr = NULL;
    Tcl_Obj *script = NULL;
    Tcl_Channel chan;

    if (TclpHasSockets(interp) != TCL_OK) {
	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) {
	case SKT_ASYNC:
	    if (server == 1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"cannot set -async option for server sockets", -1));
		return TCL_ERROR;
	    }
	    async = 1;







|





|
|


|
|
|
|
|





|
<
<











|







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
 *	Creates a socket based channel.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SocketObjCmd(
    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", "-backlog", "-myaddr", "-myport", "-reuseaddr",
	"-reuseport", "-server", NULL
    };
    enum socketOptionsEnum {
	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;

    TclInitSockets();



    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 (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
		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;
	default:
	    Tcl_Panic("Tcl_SocketObjCmd: bad option index to SocketOptions");
	}
    }
    if (server) {
	host = myaddr;		/* NULL implies INADDR_ANY */







>
>
>
>
>
>
>
>
>
>
>







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
		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
	a++;
    } else {
	Interp *iPtr;

    wrongNumArgs:
	iPtr = (Interp *) interp;
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-myaddr addr? ?-myport myport? ?-async? host port");
	iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
	Tcl_WrongNumArgs(interp, 1, objv,

		"-server command ?-reuseaddr boolean? ?-reuseport boolean? "
		"?-myaddr addr? port");
	return TCL_ERROR;
    }

    if (!server && (reusea != -1 || reusep != -1)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"options -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.
     */







|


>
|
<



|

|
|







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
	a++;
    } else {
	Interp *iPtr;

    wrongNumArgs:
	iPtr = (Interp *) interp;
	Tcl_WrongNumArgs(interp, 1, objv,
		"?-async? ?-myaddr addr? ?-myport myport? host port");
	iPtr->flags |= INTERP_ALTERNATE_WRONG_ARGS;
	Tcl_WrongNumArgs(interp, 1, objv,
		"-server command ?-backlog count? ?-myaddr addr? "
		"?-reuseaddr boolean? ?-reuseport boolean? port");

	return TCL_ERROR;
    }

    if (!server && (reusea != -1 || reusep != -1 || backlog != -1)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"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
    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,
		AcceptCallbackProc, acceptCallbackPtr);
	if (chan == NULL) {
	    Tcl_DecrRefCount(script);
	    Tcl_Free(acceptCallbackPtr);
	    return TCL_ERROR;
	}








|







1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
    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, 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
 *	handler.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FcopyObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
 *	handler.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FcopyObjCmd(
    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
    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) {
		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







|







1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
    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 (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
 *	"output"), or -1 if the channel wasn't opened for that mode.
 *
 *---------------------------------------------------------------------------
 */

static int
ChanPendingObjCmd(
    TCL_UNUSED(ClientData),
    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};


    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "mode channelId");
	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) {
    case PENDING_INPUT:
	if (!(mode & TCL_READABLE)) {
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-1));
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_InputBuffered(chan)));
	}
	break;







|





<

|
>















|







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
 *	"output"), or -1 if the channel wasn't opened for that mode.
 *
 *---------------------------------------------------------------------------
 */

static int
ChanPendingObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;

    static const char *const options[] = {"input", "output", NULL};
    enum pendingOptionsEnum {PENDING_INPUT, PENDING_OUTPUT} index;
    int mode;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "mode channelId");
	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 (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
 *	Truncates a channel (or rather a file underlying a channel).
 *
 *----------------------------------------------------------------------
 */

static int
ChanTruncateObjCmd(
    TCL_UNUSED(ClientData),
    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?");
	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) {
	    return TCL_ERROR;
	}
	if (length < 0) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "cannot truncate to negative length of file", -1));
	    return TCL_ERROR;
	}







|




















|







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
 *	Truncates a channel (or rather a file underlying a channel).
 *
 *----------------------------------------------------------------------
 */

static int
ChanTruncateObjCmd(
    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?");
	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 (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
 *	anonymous pipe.
 *
 *----------------------------------------------------------------------
 */

static int
ChanPipeObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
 *	anonymous pipe.
 *
 *----------------------------------------------------------------------
 */

static int
ChanPipeObjCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclChannelNamesCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    if (objc < 1 || objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
	return TCL_ERROR;







|







1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclChannelNamesCmd(
    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;

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
/*
 * 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 ([email protected])
 *
 * 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,
			    int mode);
static int		TransformCloseProc(ClientData instanceData,
			    Tcl_Interp *interp, int flags);
static int		TransformInputProc(ClientData instanceData, char *buf,
			    int toRead, int *errorCodePtr);
static int		TransformOutputProc(ClientData instanceData,
			    const char *buf, int toWrite, int *errorCodePtr);
static int		TransformSetOptionProc(ClientData instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *value);
static int		TransformGetOptionProc(ClientData 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);

/*
 * Forward declarations of internal procedures. Secondly the procedures for
 * handling and generating fileeevents.
 */

static void		TransformChannelHandlerTimer(ClientData clientData);

/*
 * Forward declarations of internal procedures. Third, helper procedures
 * encapsulating essential tasks.
 */

typedef struct TransformChannelData TransformChannelData;






|
|













|

|

|

|

|


|


|
|
|
|
|
|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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 © 2000 Ajuba Solutions
 * Copyright © 1999-2000 Andreas Kupries ([email protected])
 *
 * 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(void *instanceData,
			    int mode);
static int		TransformCloseProc(void *instanceData,
			    Tcl_Interp *interp, int flags);
static int		TransformInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCodePtr);
static int		TransformOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCodePtr);
static int		TransformSetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *value);
static int		TransformGetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
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(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
 */

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,
			    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.







|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
 */

typedef struct ResultBuffer ResultBuffer;

static inline void	ResultClear(ResultBuffer *r);
static inline void	ResultInit(ResultBuffer *r);
static inline int	ResultEmpty(ResultBuffer *r);
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.
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;
    TransformChannelData *dataPtr;
    Tcl_DString ds;

    if (chan == NULL) {
	return TCL_ERROR;
    }

    if (TCL_OK != Tcl_ListObjLength(interp, cmdObjPtr, &objc)) {
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("-command value is not a list", -1));
	return TCL_ERROR;
    }

    chanPtr = (Channel *) chan;
    statePtr = chanPtr->state;







|







|







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. */
    Tcl_Size objc;
    TransformChannelData *dataPtr;
    Tcl_DString ds;

    if (chan == NULL) {
	return TCL_ERROR;
    }

    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
				 * 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;
    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);







|







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). */
    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
     */

    if (preserve == P_PRESERVE) {
	state = Tcl_SaveInterpState(eval, res);
    }

    Tcl_IncrRefCount(command);
    Tcl_ListObjAppendElement(NULL, command, Tcl_NewStringObj((char *) op, -1));






    /*
     * Use a byte-array to prevent the misinterpretation of binary data coming
     * 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
     * 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;







|
>
>
>
>
>



|







|







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);
    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.
     */

    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 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
	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;



    case TRANSMIT_SELF:
	if (dataPtr->self == NULL) {
	    break;
	}
	resObj = Tcl_GetObjResult(eval);
	resBuf = TclGetByteArrayFromObj(resObj, &resLen);

	Tcl_WriteRaw(dataPtr->self, (char *) resBuf, resLen);
	break;



    case TRANSMIT_IBUF:
	resObj = Tcl_GetObjResult(eval);
	resBuf = TclGetByteArrayFromObj(resObj, &resLen);

	ResultAdd(&dataPtr->result, resBuf, resLen);
	break;







    case TRANSMIT_NUM:
	/*
	 * Interpret result as integer number.
	 */

	resObj = Tcl_GetObjResult(eval);







|
>
|
|
|
>
>






|
>
|
|
>
>



|
>
|
|
>
>
>
>
>
>







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 = 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 = 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 = Tcl_GetBytesFromObj(NULL, resObj, &resLen);
	if (resBuf) {
	    ResultAdd(&dataPtr->result, resBuf, resLen);
	    break;
	}
	nonBytes:
	Tcl_AppendResult(interp, "chan transform callback received non-bytes",
		(void *)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
 *	0 if successful, errno when failed.
 *
 *----------------------------------------------------------------------
 */

static int
TransformBlockModeProc(
    ClientData instanceData,	/* State of transformation. */
    int mode)			/* New blocking mode. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;

    if (mode == TCL_MODE_NONBLOCKING) {
	dataPtr->flags |= CHANNEL_ASYNC;
    } else {







|







511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
 *	0 if successful, errno when failed.
 *
 *----------------------------------------------------------------------
 */

static int
TransformBlockModeProc(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TransformCloseProc(
    ClientData instanceData,
    Tcl_Interp *interp,
	int flags)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
	return EINVAL;







|







543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TransformCloseProc(
    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
	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).
     */

    PreserveData(dataPtr);
    if (dataPtr->mode & TCL_WRITABLE) {
	ExecuteCallback(dataPtr, interp, A_FLUSH_WRITE, NULL, 0,
		TRANSMIT_DOWN, P_PRESERVE);
    }







|







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. 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
 *	A transformed buffer.
 *
 *----------------------------------------------------------------------
 */

static int
TransformInputProc(
    ClientData instanceData,
    char *buf,
    int toRead,
    int *errorCodePtr)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;
    int gotBytes, read, copied;
    Tcl_Channel downChan;







|







627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
 *	A transformed buffer.
 *
 *----------------------------------------------------------------------
 */

static int
TransformInputProc(
    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
 *	A transformed buffer.
 *
 *----------------------------------------------------------------------
 */

static int
TransformOutputProc(
    ClientData instanceData,
    const char *buf,
    int toWrite,
    int *errorCodePtr)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;

    /*







|







794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
 *	A transformed buffer.
 *
 *----------------------------------------------------------------------
 */

static int
TransformOutputProc(
    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
 * 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
TransformWideSeekProc(
    ClientData instanceData,	/* The channel to manipulate. */
    Tcl_WideInt 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);
    Tcl_DriverWideSeekProc *parentWideSeekProc =
	    Tcl_ChannelWideSeekProc(parentType);
    ClientData 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.
	 */








|

|
|








|







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 long long
TransformWideSeekProc(
    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);
    Tcl_DriverWideSeekProc *parentWideSeekProc =
	    Tcl_ChannelWideSeekProc(parentType);
    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.
	 */

906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
 *	A standard TCL error code.
 *
 *----------------------------------------------------------------------
 */

static int
TransformSetOptionProc(
    ClientData instanceData,
    Tcl_Interp *interp,
    const char *optionName,
    const char *value)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;
    Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self);
    Tcl_DriverSetOptionProc *setOptionProc;







|







924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
 *	A standard TCL error code.
 *
 *----------------------------------------------------------------------
 */

static int
TransformSetOptionProc(
    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
 *	A standard TCL error code.
 *
 *----------------------------------------------------------------------
 */

static int
TransformGetOptionProc(
    ClientData instanceData,
    Tcl_Interp *interp,
    const char *optionName,
    Tcl_DString *dsPtr)
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;
    Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self);
    Tcl_DriverGetOptionProc *getOptionProc;







|







962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
 *	A standard TCL error code.
 *
 *----------------------------------------------------------------------
 */

static int
TransformGetOptionProc(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TransformWatchProc(
    ClientData 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
     * are forwarding the call to the underlying channel now.
     */

    dataPtr->watchMask = mask;

    /*
     * No channel handlers any more. We will be notified automatically about







|






|







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(
    void *instanceData,	/* Channel to watch. */
    int mask)			/* Events of interest. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)instanceData;
    Tcl_Channel downChan;

    /*
     * 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
 *	The appropriate Tcl_File or NULL if not present.
 *
 *----------------------------------------------------------------------
 */

static int
TransformGetFileHandleProc(
    ClientData instanceData,	/* Channel to query. */
    int direction,		/* Direction of interest. */
    ClientData *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.
     */







|

|







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(
    void *instanceData,	/* Channel to query. */
    int direction,		/* Direction of interest. */
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TransformNotifyProc(
    ClientData clientData,	/* The state of the notified
				 * transformation. */
    int mask)			/* The mask of occuring events. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)clientData;

    /*
     * An event occured 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







|

|




|







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(
    void *clientData,	/* The state of the notified
				 * transformation. */
    int mask)			/* The mask of occurring events. */
{
    TransformChannelData *dataPtr = (TransformChannelData *)clientData;

    /*
     * 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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TransformChannelHandlerTimer(
    ClientData 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







|







1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TransformChannelHandlerTimer(
    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

/*
 *----------------------------------------------------------------------
 *
 * ResultInit --
 *
 *	Initializes the specified buffer structure. The structure will contain
 *	valid information for an emtpy buffer.
 *
 * Side effects:
 *	See above.
 *
 * Result:
 *	None.
 *







|







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 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
 *
 * Result:
 *	The number of actually copied bytes, possibly less than 'toRead'.
 *
 *----------------------------------------------------------------------
 */

static inline int
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) {
	/*
	 * Nothing to copy in the case of an empty buffer.
	 */

	return 0;
    } else if (r->used == toRead) {
	/*







|





|







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 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 (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

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) {
	/*
	 * Extension of the internal buffer is required.
	 */

	if (r->allocated == 0) {
	    r->allocated = toWrite + INCREMENT;
	    r->buf = (unsigned char *)Tcl_Alloc(r->allocated);







|







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 + 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
/*
 * 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
 *
 * 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,
			    Tcl_Interp *interp, int flags);
static int		ReflectInput(ClientData clientData, char *buf,
			    int toRead, int *errorCodePtr);
static int		ReflectOutput(ClientData clientData, const char *buf,
			    int toWrite, int *errorCodePtr);
static void		ReflectWatch(ClientData clientData, int mask);
static int		ReflectBlock(ClientData clientData, int mode);
#if TCL_THREADS
static void		ReflectThread(ClientData clientData, int action);
static int		ReflectEventRun(Tcl_Event *ev, int flags);
static int		ReflectEventDelete(Tcl_Event *ev, ClientData cd);
#endif
static Tcl_WideInt	ReflectSeekWide(ClientData clientData,
			    Tcl_WideInt offset, int mode, int *errorCodePtr);
static int		ReflectGetOption(ClientData clientData,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static int		ReflectSetOption(ClientData clientData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *newValue);


static void     TimerRunRead(ClientData clientData);
static void     TimerRunWrite(ClientData clientData);

/*
 * The C layer channel type/driver definition used by the reflection. This is
 * 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 */
#if TCL_THREADS
    ReflectThread,         /* thread action, tracking owner */
#else
	NULL,		   /* thread action */
#endif
    NULL		   /* truncate */
};

/*
 * Instance data for a reflected channel. ===========================
 */

typedef struct {












|




















|

|

|

|
|

|

|

|
|
|


|


>
>
|
|


|
<













|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*
 * 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 © 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(void *clientData,
			    Tcl_Interp *interp, int flags);
static int		ReflectInput(void *clientData, char *buf,
			    int toRead, int *errorCodePtr);
static int		ReflectOutput(void *clientData, const char *buf,
			    int toWrite, int *errorCodePtr);
static void		ReflectWatch(void *clientData, int mask);
static int		ReflectBlock(void *clientData, int mode);
#if TCL_THREADS
static void		ReflectThread(void *clientData, int action);
static int		ReflectEventRun(Tcl_Event *ev, int flags);
static int		ReflectEventDelete(Tcl_Event *ev, void *cd);
#endif
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(void *clientData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *newValue);
static int		ReflectTruncate(void *clientData,
			    long long length);
static void		TimerRunRead(void *clientData);
static void		TimerRunWrite(void *clientData);

/*
 * The C layer channel type/driver definition used by the reflection.

 */

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 */
#if TCL_THREADS
    ReflectThread,         /* thread action, tracking owner */
#else
	NULL,		   /* thread action */
#endif
    ReflectTruncate	   /* Truncate.				NULL'able */
};

/*
 * Instance data for a reflected channel. ===========================
 */

typedef struct {
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
    /*
     * 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.
     *
     * 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
     * ef28eb1f1516.
     */
} ReflectedChannel;

/*
 * Structure of the table maping 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.







|








|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
    /*
     * 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 'refchan', 'memchan', etc.
     *
     * 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
     * ef28eb1f1516.
     */
} ReflectedChannel;

/*
 * 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
    "cget",		/* OPT \/ Together or none */
    "cgetall",		/* OPT /\ of these two     */
    "configure",	/* OPT */
    "finalize",		/*     */
    "initialize",	/*     */
    "read",		/* OPT */
    "seek",		/* OPT */

    "watch",		/*     */
    "write",		/* OPT */
    NULL
};
typedef enum {
    METH_BLOCKING,
    METH_CGET,
    METH_CGETALL,
    METH_CONFIGURE,
    METH_FINAL,
    METH_INIT,
    METH_READ,
    METH_SEEK,

    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))


#define RANDW \
	(TCL_READABLE | TCL_WRITABLE)

#define IMPLIES(a,b)	((!(a)) || (b))
#define NEGIMPL(a,b)
#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'.







>













>









|
>






|







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    "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_TRUNCATE))

#define RANDW \
	(TCL_READABLE | TCL_WRITABLE)

#define IMPLIES(a,b)	((!(a)) || (b))
#define NEGIMPL(a,b)
#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
    ForwardedInput,
    ForwardedOutput,
    ForwardedSeek,
    ForwardedWatch,
    ForwardedBlock,
    ForwardedSetOpt,
    ForwardedGetOpt,
    ForwardedGetOptAll

} 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),







|
>







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    ForwardedInput,
    ForwardedOutput,
    ForwardedSeek,
    ForwardedWatch,
    ForwardedBlock,
    ForwardedSetOpt,
    ForwardedGetOpt,
    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
 * 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,
				 * 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,
				 * 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 */







|





|







262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
 * 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 */
    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 */
    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
    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 */
};





/*
 * 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;

} ForwardParam;

/*
 * Forward declaration.
 */

typedef struct ForwardingResult ForwardingResult;







>
>
>
>














>







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
    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
 * 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);

#define FreeReceivedError(p) \
	if ((p)->base.mustFree) {                               \
	    Tcl_Free((p)->base.msgStr);                           \
	}
#define PassReceivedErrorInterp(i,p) \
	if ((i) != NULL) {                                      \







|







396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
 * 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(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

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 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_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}";







|

















>







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

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 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
 *	Creates a new channel.
 *
 *----------------------------------------------------------------------
 */

int
TclChanCreateObjCmd(
    TCL_UNUSED(ClientData),
    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_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 */







|












|







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
 *	Creates a new channel.
 *
 *----------------------------------------------------------------------
 */

int
TclChanCreateObjCmd(
    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 */
    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 */
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
    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.
     */

    modeObj = objv[MODE];
    if (EncodeEventMask(interp, "mode", objv[MODE], &mode) != TCL_OK) {
	return TCL_ERROR;
    }








|







545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
    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".
     * 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

    /*
     * Now create the channel.
     */

    rcId = NextHandle();
    rcPtr = NewReflectedChannel(interp, cmdObj, mode, rcId);




    /*
     * 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







>
>
>







576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592

    /*
     * 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
    /*
     * 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)));
	Tcl_DecrRefCount(resObj);
	goto error;
    }








|







608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
    /*
     * 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 (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;
    }

691
692
693
694
695
696
697



698
699
700
701
702
703
704
	}
	if (!(methods & FLAG(METH_BLOCKING))) {
	    clonePtr->blockModeProc = NULL;
	}
	if (!(methods & FLAG(METH_SEEK))) {
	    clonePtr->wideSeekProc = NULL;
	}




	chanPtr->typePtr = clonePtr;
    }

    /*
     * Register the channel in the I/O system, and in our our map for 'chan
     * postevent'.







>
>
>







705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
	}
	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
     * postevent'.
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
    Tcl_NotifyChannel(e->rcPtr->chan, e->events);
    return 1;
}

static int
ReflectEventDelete(
    Tcl_Event *ev,
    ClientData 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 1;
}
#endif

int
TclChanPostEventObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    /*
     * Ensure -> HANDLER thread
     *







|



















|







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
    Tcl_NotifyChannel(e->rcPtr->chan, e->events);
    return 1;
}

static int
ReflectEventDelete(
    Tcl_Event *ev,
    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 1;
}
#endif

int
TclChanPostEventObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    /*
     * Ensure -> HANDLER thread
     *
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

    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);
	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
     * have gone seriously haywire.
     */

    chan = (Tcl_Channel)Tcl_GetHashValue(hPtr);
    chanTypePtr = Tcl_GetChannelType(chan);

    /*







|















|
|







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

    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, (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 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);

    /*
903
904
905
906
907
908
909





910
911
912
913
914
915
916
    /*
     * 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;





    }

    /*
     * Check that the channel is actually interested in the provided events.
     */

    if (events & ~rcPtr->interest) {







>
>
>
>
>







920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
    /*
     * 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) {
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
         * 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);
    }
#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);
}

/*







|
|
















|








|







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
         * 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_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(
    void *clientData)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    rcPtr->readTimer = NULL;
    Tcl_NotifyChannel(rcPtr->chan, TCL_READABLE);
}

static void
TimerRunWrite(
    void *clientData)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    rcPtr->writeTimer = NULL;
    Tcl_NotifyChannel(rcPtr->chan, TCL_WRITABLE);
}

/*
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
}

static void
UnmarshallErrorResult(
    Tcl_Interp *interp,
    Tcl_Obj *msgObj)
{
    int lc;
    Tcl_Obj **lv;
    int explicitResult;
    int 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) {
	Tcl_Panic("TclChanCaughtErrorBypass: Bad syntax of caught result");
    }
    if (interp == NULL) {
	return;
    }

    explicitResult = lc & 1;		/* Odd number of values? */







|


|







|



|







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
}

static void
UnmarshallErrorResult(
    Tcl_Interp *interp,
    Tcl_Obj *msgObj)
{
    Tcl_Size lc;
    Tcl_Obj **lv;
    int explicitResult;
    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 marshal the
     * information; if we panic here, something has gone badly wrong already.
     */

    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

/*
 *----------------------------------------------------------------------
 *
 * ReflectClose --
 *
 *	This function is invoked when the channel is closed, to delete the
 *	driver specific instance data.
 *
 * Results:
 *	A posix error.
 *
 * Side effects:
 *	Releases memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectClose(
    ClientData 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
	 * finalization functions.
	 */

	/*
	 * THREADED => Forward this to the origin thread
	 *
	 * Note: DeleteThreadReflectedChannelMap() is the thread exit handler







|


|









|



















|
|







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

/*
 *----------------------------------------------------------------------
 *
 * ReflectClose --
 *
 *	This function is invoked when the channel is closed, to delete the
 *	driver-specific instance data.
 *
 * Results:
 *	A Posix error.
 *
 * Side effects:
 *	Releases memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectClose(
    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. 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
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
	}
	if (rcPtr->readTimer != NULL) {
	    Tcl_DeleteTimerHandler(rcPtr->readTimer);
	}
	if (rcPtr->writeTimer != NULL) {
	    Tcl_DeleteTimerHandler(rcPtr->writeTimer);
	}
        Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
	return EOK;
    }

    /*
     * Are we in the correct thread?
     */








|







1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
	}
	if (rcPtr->readTimer != NULL) {
	    Tcl_DeleteTimerHandler(rcPtr->readTimer);
	}
	if (rcPtr->writeTimer != NULL) {
	    Tcl_DeleteTimerHandler(rcPtr->writeTimer);
	}
	Tcl_EventuallyFree(rcPtr, FreeReflectedChannel);
	return EOK;
    }

    /*
     * Are we in the correct thread?
     */

1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
    }
    if (rcPtr->readTimer != NULL) {
	Tcl_DeleteTimerHandler(rcPtr->readTimer);
    }
    if (rcPtr->writeTimer != NULL) {
	Tcl_DeleteTimerHandler(rcPtr->writeTimer);
    }
    Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
    return (result == TCL_OK) ? EOK : EINVAL;
}

/*
 *----------------------------------------------------------------------
 *
 * ReflectInput --







|







1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
    }
    if (rcPtr->readTimer != NULL) {
	Tcl_DeleteTimerHandler(rcPtr->readTimer);
    }
    if (rcPtr->writeTimer != NULL) {
	Tcl_DeleteTimerHandler(rcPtr->writeTimer);
    }
    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
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectInput(
    ClientData clientData,
    char *buf,
    int toRead,
    int *errorCodePtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *toReadObj;
    size_t 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?
     */








|






|







1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectInput(
    void *clientData,
    char *buf,
    int toRead,
    int *errorCodePtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *toReadObj;
    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?
     */

1365
1366
1367
1368
1369
1370
1371
1372
1373



1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
            goto error;
	}

	Tcl_SetChannelError(rcPtr->chan, resObj);
        goto invalid;
    }

    bytev = TclGetByteArrayFromObj(resObj, &bytec);




    if ((size_t)toRead < bytec) {
	SetChannelErrorStr(rcPtr->chan, msg_read_toomuch);
	goto invalid;
    }

    *errorCodePtr = EOK;

    if (bytec + 1 > 1) {
	memcpy(buf, bytev, bytec);
    }

 stop:
    Tcl_DecrRefCount(toReadObj);
    Tcl_DecrRefCount(resObj);		/* Remove reference held from invoke */
    Tcl_Release(rcPtr);







|

>
>
>
|






|







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
            goto error;
	}

	Tcl_SetChannelError(rcPtr->chan, resObj);
        goto invalid;
    }

    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);

    if (bytev == NULL) {
	SetChannelErrorStr(rcPtr->chan, msg_read_nonbyte);
	goto invalid;
    } else if (toRead < bytec) {
	SetChannelErrorStr(rcPtr->chan, msg_read_toomuch);
	goto invalid;
    }

    *errorCodePtr = EOK;

    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
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectOutput(
    ClientData clientData,
    const char *buf,
    int toWrite,
    int *errorCodePtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *bufObj;
    Tcl_Obj *resObj;		/* Result data for 'write' */







|







1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectOutput(
    void *clientData,
    const char *buf,
    int toWrite,
    int *errorCodePtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *bufObj;
    Tcl_Obj *resObj;		/* Result data for 'write' */
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
 *
 * Side effects:
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideInt
ReflectSeekWide(
    ClientData clientData,
    Tcl_WideInt offset,
    int seekMode,
    int *errorCodePtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *offObj, *baseObj;
    Tcl_Obj *resObj;		/* Result for 'seek' */
    Tcl_WideInt newLoc;







|

|
|







1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
 *
 * Side effects:
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static long long
ReflectSeekWide(
    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;
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
    Tcl_IncrRefCount(baseObj);

    if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK) {
	Tcl_SetChannelError(rcPtr->chan, resObj);
        goto invalid;
    }

    if (Tcl_GetWideIntFromObj(rcPtr->interp, resObj, &newLoc) != TCL_OK) {
	Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp));
        goto invalid;
    }

    if (newLoc < 0) {
	SetChannelErrorStr(rcPtr->chan, msg_seek_beforestart);
        goto invalid;







|







1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
    Tcl_IncrRefCount(baseObj);

    if (InvokeTclMethod(rcPtr, METH_SEEK, offObj, baseObj, &resObj)!=TCL_OK) {
	Tcl_SetChannelError(rcPtr->chan, resObj);
        goto invalid;
    }

    if (TclGetWideIntFromObj(rcPtr->interp, resObj, &newLoc) != TCL_OK) {
	Tcl_SetChannelError(rcPtr->chan, MarshallError(rcPtr->interp));
        goto invalid;
    }

    if (newLoc < 0) {
	SetChannelErrorStr(rcPtr->chan, msg_seek_beforestart);
        goto invalid;
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static void
ReflectWatch(
    ClientData clientData,
    int mask)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *maskObj;

    /*
     * We restrict the interest to what the channel can support. IOW there







|







1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static void
ReflectWatch(
    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
 *
 * ReflectBlock --
 *
 *	This function is invoked to tell the channel which blocking behaviour
 *	is required of it.
 *
 * Results:
 *	A posix error number.
 *
 * Side effects:
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectBlock(
    ClientData clientData,
    int nonblocking)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;
    Tcl_Obj *blockObj;
    int errorNum;		/* EINVAL or EOK (success). */
    Tcl_Obj *resObj;		/* Result data for 'blocking' */








|









|







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
 *
 * ReflectBlock --
 *
 *	This function is invoked to tell the channel which blocking behaviour
 *	is required of it.
 *
 * Results:
 *	A Posix error number.
 *
 * Side effects:
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectBlock(
    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
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static void
ReflectThread(
    ClientData clientData,
    int action)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;

    switch (action) {
    case TCL_CHANNEL_THREAD_INSERT:
        rcPtr->owner = Tcl_GetCurrentThread();







|







1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static void
ReflectThread(
    void *clientData,
    int action)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *)clientData;

    switch (action) {
    case TCL_CHANNEL_THREAD_INSERT:
        rcPtr->owner = Tcl_GetCurrentThread();
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
 *	Arbitrary, as it calls upon a Tcl script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectSetOption(
    ClientData 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' */







|







1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
 *	Arbitrary, as it calls upon a Tcl script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectSetOption(
    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
 *	Arbitrary, as it calls upon a Tcl script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectGetOption(
    ClientData 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' */

    int listc, result = TCL_OK;
    Tcl_Obj **listv;
    MethodName method;

    /*
     * Are we in the correct thread?
     */








|












>
|







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
 *	Arbitrary, as it calls upon a Tcl script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectGetOption(
    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 result = TCL_OK;
    Tcl_Obj **listv;
    MethodName method;

    /*
     * Are we in the correct thread?
     */

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
    /*
     * 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 ((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,
		(listc == 1 ? "" : "s")));
        goto error;
    } else {
	size_t len;
	const char *str = TclGetStringFromObj(resObj, &len);

	if (len) {
	    TclDStringAppendLiteral(dsPtr, " ");
	    Tcl_DStringAppend(dsPtr, str, len);
	}
        goto ok;







|











|



|







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
    /*
     * 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 (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 %" TCL_SIZE_MODIFIER "d element%s instead", listc,
		(listc == 1 ? "" : "s")));
        goto error;
    } else {
	Tcl_Size len;
	const char *str = TclGetStringFromObj(resObj, &len);

	if (len) {
	    TclDStringAppendLiteral(dsPtr, " ");
	    Tcl_DStringAppend(dsPtr, str, len);
	}
        goto ok;
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
    Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
    Tcl_Release(rcPtr);
    return result;
 error:
    result = TCL_ERROR;
    goto stop;
}




































































/*
 * 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.
 *
 * 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_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) {
	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) {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|
|
|
|




















|




|
<
<
<
<
<
<







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
    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 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 */
    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 (TclListObjGetElements(interp, obj, &listc, &listv) != TCL_OK) {






	return TCL_ERROR;
    }

    events = 0;
    while (listc > 0) {
	if (Tcl_GetIndexFromObj(interp, listv[listc-1], eventOptions,
		objName, 0, &evIndex) != TCL_OK) {
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
    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));
    }







<







2257
2258
2259
2260
2261
2262
2263

2264
2265
2266
2267
2268
2269
2270
    rcPtr->writeTimer = 0;
#if TCL_THREADS
    rcPtr->thread = Tcl_GetCurrentThread();
#endif
    rcPtr->mode = mode;
    rcPtr->interest = 0;		/* Initially no interest registered */


    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
 *	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
 *	threads for a short time.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
NextHandle(void)







|







2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
 *	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
 *	threads for a short time.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Obj *
NextHandle(void)
2228
2229
2230
2231
2232
2233
2234
2235
2236

2237
2238
2239
2240
2241
2242
2243
    Tcl_MutexUnlock(&rcCounterMutex);

    return resObj;
}

static void
FreeReflectedChannel(
    ReflectedChannel *rcPtr)
{

    Channel *chanPtr = (Channel *) rcPtr->chan;

    TclChannelRelease((Tcl_Channel)chanPtr);
    if (rcPtr->name) {
	Tcl_DecrRefCount(rcPtr->name);
    }
    if (rcPtr->methods) {







|

>







2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
    Tcl_MutexUnlock(&rcCounterMutex);

    return resObj;
}

static void
FreeReflectedChannel(
    void *blockPtr)
{
    ReflectedChannel *rcPtr = (ReflectedChannel *) blockPtr;
    Channel *chanPtr = (Channel *) rcPtr->chan;

    TclChannelRelease((Tcl_Channel)chanPtr);
    if (rcPtr->name) {
	Tcl_DecrRefCount(rcPtr->name);
    }
    if (rcPtr->methods) {
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	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:







|







2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352

/*
 *----------------------------------------------------------------------
 *
 * InvokeTclMethod --
 *
 *	This function is used to invoke the Tcl level of a reflected channel.
 *	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
    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. */
    Tcl_Obj *cmd;

    if (rcPtr->dead) {
	/*
	 * The channel is marked as dead. Bail out immediately, with an
	 * appropriate error.
	 */







|
|







2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
    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 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.
	 */
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323

    /*
     * 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.







<







2396
2397
2398
2399
2400
2401
2402

2403
2404
2405
2406
2407
2408
2409

    /*
     * 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
	     * 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;
		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,







|







2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
	     * 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_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
 *	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
 *	registered in this interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
MarkDead(







|







2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
 *	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 channelEvent handlers that were
 *	registered in this interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
MarkDead(
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
	rcPtr->cmd = NULL;
    }
    rcPtr->dead = 1;
}

static void
DeleteReflectedChannelMap(
    ClientData 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;







|







2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
	rcPtr->cmd = NULL;
    }
    rcPtr->dead = 1;
}

static void
DeleteReflectedChannelMap(
    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;
2651
2652
2653
2654
2655
2656
2657


2658
2659
2660
2661
2662
2663
2664

	    continue;
	}

	MarkDead(rcPtr);
	Tcl_DeleteHashEntry(hPtr);
    }


#endif
}

#if TCL_THREADS
/*
 *----------------------------------------------------------------------
 *







>
>







2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752

	    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
 *	Deletes the hash table of channels.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteThreadReflectedChannelMap(
    TCL_UNUSED(ClientData))
{
    Tcl_HashSearch hSearch;	 /* Search variable. */
    Tcl_HashEntry *hPtr;	 /* Search variable. */
    Tcl_ThreadId self = Tcl_GetCurrentThread();
    ReflectedChannelMap *rcmPtr; /* The map */
    ForwardingResult *resultPtr;


    /*
     * 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.
     */








|






>







2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
 *	Deletes the hash table of channels.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteThreadReflectedChannelMap(
    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.
     */

2792
2793
2794
2795
2796
2797
2798

2799
2800
2801
2802
2803
2804
2805
    /*
     * 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();

    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
    /*
     * 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

    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);

    /*
     * (*) Block until the handler thread has either processed the transfer or
     * rejected it.
     */

    while (resultPtr->result < 0) {







|
|







2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986

    Tcl_CreateThreadExitHandler(SrcExitProc, evPtr);

    /*
     * Queue the event and poke the other thread's notifier.
     */

    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) {
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043



3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
	    }
	    paramPtr->input.toRead = TCL_IO_FAILURE;
	} else {
	    /*
	     * Process a regular result.
	     */

	    size_t bytec = 0;		/* Number of returned bytes */
	    unsigned char *bytev;	/* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);




	    if (paramPtr->input.toRead < bytec) {
		ForwardSetStaticError(paramPtr, msg_read_toomuch);
		paramPtr->input.toRead = TCL_IO_FAILURE;
	    } else {
		if (bytec + 1 > 1) {
		    memcpy(paramPtr->input.buf, bytev, bytec);
		}
		paramPtr->input.toRead = bytec;
	    }
	}
        Tcl_Release(rcPtr);
        Tcl_DecrRefCount(toReadObj);







|


|

>
>
>
|



|







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
	    }
	    paramPtr->input.toRead = TCL_IO_FAILURE;
	} else {
	    /*
	     * Process a regular result.
	     */

	    Tcl_Size bytec = 0;		/* Number of returned bytes */
	    unsigned char *bytev;	/* Array of returned bytes */

	    bytev = Tcl_GetBytesFromObj(NULL, resObj, &bytec);

	    if (bytev == NULL) {
		ForwardSetStaticError(paramPtr, msg_read_nonbyte);
		paramPtr->input.toRead = -1;
	    } else if (paramPtr->input.toRead < bytec) {
		ForwardSetStaticError(paramPtr, msg_read_toomuch);
		paramPtr->input.toRead = TCL_IO_FAILURE;
	    } else {
		if (bytec > 0) {
		    memcpy(paramPtr->input.buf, bytev, bytec);
		}
		paramPtr->input.toRead = bytec;
	    }
	}
        Tcl_Release(rcPtr);
        Tcl_DecrRefCount(toReadObj);
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
	    /*
	     * 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 (newLoc < 0) {
		    ForwardSetStaticError(paramPtr, msg_seek_beforestart);
		    paramPtr->seek.offset = -1;
		} else {
		    paramPtr->seek.offset = newLoc;
		}
	    } else {







|







3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
	    /*
	     * Process a regular result. If the type is wrong this may change
	     * into an error.
	     */

	    Tcl_WideInt newLoc;

	    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 {
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
	    ForwardSetObjError(paramPtr, resObj);
	} else {
	    /*
	     * Extract list, validate that it is a list, and #elements. See
	     * NOTE (4) as well.
	     */

	    int listc;
	    Tcl_Obj **listv;

	    if (Tcl_ListObjGetElements(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}",
			listc, (listc == 1 ? "element" : "elements"));

		ForwardSetDynamicError(paramPtr, buf);
	    } else {
		size_t len;
		const char *str = TclGetStringFromObj(resObj, &len);

		if (len) {
		    TclDStringAppendLiteral(paramPtr->getOpt.value, " ");
		    Tcl_DStringAppend(paramPtr->getOpt.value, str, len);
		}
	    }
	}
        Tcl_Release(rcPtr);
	break;














    default:
	/*
	 * Bad operation code.
	 */

	Tcl_Panic("Bad operation code in ForwardProc");







|


|










|
|




|










>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    ForwardSetObjError(paramPtr, resObj);
	} else {
	    /*
	     * Extract list, validate that it is a list, and #elements. See
	     * NOTE (4) as well.
	     */

	    Tcl_Size listc;
	    Tcl_Obj **listv;

	    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);
		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 {
		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);
	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
    }

    return 1;
}

static void
SrcExitProc(
    ClientData clientData)
{
    ForwardingEvent *evPtr = (ForwardingEvent *)clientData;
    ForwardingResult *resultPtr;
    ForwardParam *paramPtr;

    /*
     * NOTE (2): Can this handler be called with the originator blocked?







|







3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
    }

    return 1;
}

static void
SrcExitProc(
    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
}

static void
ForwardSetObjError(
    ForwardParam *paramPtr,
    Tcl_Obj *obj)
{
    size_t len;
    const char *msgStr = TclGetStringFromObj(obj, &len);

    len++;
    ForwardSetDynamicError(paramPtr, Tcl_Alloc(len));
    memcpy(paramPtr->base.msgStr, msgStr, len);
}
#endif







|







3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
}

static void
ForwardSetObjError(
    ForwardParam *paramPtr,
    Tcl_Obj *obj)
{
    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
/*
 * 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.
 *
 * 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,
			    Tcl_Interp *interp, int flags);
static int		ReflectInput(ClientData clientData, char *buf,
			    int toRead, int *errorCodePtr);
static int		ReflectOutput(ClientData 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,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static int		ReflectSetOption(ClientData 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);

/*
 * The C layer channel type/driver definition used by the reflection.
 */

static const Tcl_ChannelType tclRTransformType = {
    "tclrtransform",		/* Type name. */












|




















|

|

|

|
|
|
|
|


|


|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
 * 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 © 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(void *clientData,
			    Tcl_Interp *interp, int flags);
static int		ReflectInput(void *clientData, char *buf,
			    int toRead, int *errorCodePtr);
static int		ReflectOutput(void *clientData, const char *buf,
			    int toWrite, int *errorCodePtr);
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(void *clientData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *newValue);
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. */
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
 * 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,
				 * <= 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);

#define RB_INCREMENT (512)

/*
 * Convenience macro to make some casts easier to use.
 */








|






|
|
|
|
|
|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
 * 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,
				 * <= allocated. */
} ResultBuffer;

#define ResultLength(r) ((r)->used)
/* static int		ResultLength(ResultBuffer *r); */

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
#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))

#if TCL_THREADS
/*
 * Thread specific types and structures.
 *
 * We are here essentially creating a very specific implementation of 'thread
 * send'.







|







208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#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))

#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
 * 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,
				 * O: #bytes in the transform result */
};
struct ForwardParamLimit {
    ForwardParamBase base;	/* "Supertype". MUST COME FIRST. */
    int max;			/* O: Character read limit */
};








|







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
 * 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 */
    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
 * 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);

#define FreeReceivedError(p) \
	do {								\
	    if ((p)->base.mustFree) {					\
		Tcl_Free((p)->base.msgStr);				\
	    }								\
	} while (0)







|







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
 * 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(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
	    (p)->base.msgStr = (char *) (emsg);				\
	} while (0)

static void		ForwardSetObjError(ForwardParam *p,
			    Tcl_Obj *objPtr);
static ReflectedTransformMap *	GetThreadReflectedTransformMap(void);
static void		DeleteThreadReflectedTransformMap(
			    ClientData 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 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,
			    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].







|


















|






|







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
	    (p)->base.msgStr = (char *) (emsg);				\
	} while (0)

static void		ForwardSetObjError(ForwardParam *p,
			    Tcl_Obj *objPtr);
static ReflectedTransformMap *	GetThreadReflectedTransformMap(void);
static void		DeleteThreadReflectedTransformMap(
			    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 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(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
/*
 * 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 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);







|







446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
/*
 * 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(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
 *	Creates a new channel.
 *
 *----------------------------------------------------------------------
 */

int
TclChanPushObjCmd(
    TCL_UNUSED(ClientData),
    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_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







|















|







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
 *	Creates a new channel.
 *
 *----------------------------------------------------------------------
 */

int
TclChanPushObjCmd(
    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 */
    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
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

    /*
     * 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)));
	Tcl_DecrRefCount(resObj);
	goto error;
    }








|







595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

    /*
     * 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 (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;
    }

630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
                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
     * 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;
    }







|







630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
                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 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;
    }
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723

  error:
    /*
     * We are not going through ReflectClose as we never had a channel
     * structure.
     */

    Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
    return TCL_ERROR;

#undef CHAN
#undef CMD
}

/*







|







709
710
711
712
713
714
715
716
717
718
719
720
721
722
723

  error:
    /*
     * We are not going through ReflectClose as we never had a channel
     * structure.
     */

    Tcl_EventuallyFree(rtPtr, FreeReflectedTransform);
    return TCL_ERROR;

#undef CHAN
#undef CMD
}

/*
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
 *	latter implies that arbitrary side effects are possible.
 *
 *----------------------------------------------------------------------
 */

int
TclChanPopObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    /*
     * Syntax:   chan pop CHANNEL
     *           [0]  [1] [2]







|







736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
 *	latter implies that arbitrary side effects are possible.
 *
 *----------------------------------------------------------------------
 */

int
TclChanPopObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    /*
     * Syntax:   chan pop CHANNEL
     *           [0]  [1] [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
841
842
843
844
845
}

static void
UnmarshallErrorResult(
    Tcl_Interp *interp,
    Tcl_Obj *msgObj)
{
    int lc;
    Tcl_Obj **lv;
    int explicitResult;
    int 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) {
	Tcl_Panic("TclChanCaughtErrorBypass: Bad syntax of caught result");
    }
    if (interp == NULL) {
	return;
    }

    explicitResult = lc & 1;		/* Odd number of values? */







|


|











|







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
}

static void
UnmarshallErrorResult(
    Tcl_Interp *interp,
    Tcl_Obj *msgObj)
{
    Tcl_Size lc;
    Tcl_Obj **lv;
    int explicitResult;
    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 (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
 *
 * ReflectClose --
 *
 *	This function is invoked when the channel is closed, to delete the
 *	driver specific instance data.
 *
 * Results:
 *	A posix error.
 *
 * Side effects:
 *	Releases memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectClose(
    ClientData 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' */







|









|







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
 *
 * ReflectClose --
 *
 *	This function is invoked when the channel is closed, to delete the
 *	driver specific instance data.
 *
 * Results:
 *	A Posix error.
 *
 * Side effects:
 *	Releases memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectClose(
    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

	    if (result != TCL_OK) {
		FreeReceivedError(&p);
	    }
	}
#endif /* TCL_THREADS */

	Tcl_EventuallyFree(rtPtr, (Tcl_FreeProc *) 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);
		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);
		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);

	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.
     */

    result = InvokeTclMethod(rtPtr, "finalize", NULL, NULL, &resObj);
    if ((result != TCL_OK) && (interp != NULL)) {
	Tcl_SetChannelErrorInterp(interp, resObj);
    }








|
















|













|



















|










|







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

	    if (result != TCL_OK) {
		FreeReceivedError(&p);
	    }
	}
#endif /* TCL_THREADS */

	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,
			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,
			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, FreeReflectedTransform);

	if (result != TCL_OK) {
	    PassReceivedErrorInterp(interp, &p);
	    return EINVAL;
	}
	return EOK;
    }
#endif /* TCL_THREADS */

    /*
     * 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
	hPtr = Tcl_FindHashEntry(&rtmPtr->map, TclGetString(rtPtr->handle));
	if (hPtr) {
	    Tcl_DeleteHashEntry(hPtr);
	}
#endif /* TCL_THREADS */
    }

    Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
    return errorCodeSet ? errorCode : ((result == TCL_OK) ? EOK : EINVAL);
}

/*
 *----------------------------------------------------------------------
 *
 * ReflectInput --







|







1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
	hPtr = Tcl_FindHashEntry(&rtmPtr->map, TclGetString(rtPtr->handle));
	if (hPtr) {
	    Tcl_DeleteHashEntry(hPtr);
	}
#endif /* TCL_THREADS */
    }

    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
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectInput(
    ClientData clientData,
    char *buf,
    int toRead,
    int *errorCodePtr)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;
    int gotBytes, copied, readBytes;
    Tcl_Obj *bufObj;







|







1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectInput(
    void *clientData,
    char *buf,
    int toRead,
    int *errorCodePtr)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;
    int gotBytes, copied, readBytes;
    Tcl_Obj *bufObj;
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectOutput(
    ClientData clientData,
    const char *buf,
    int toWrite,
    int *errorCodePtr)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    /*







|







1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectOutput(
    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
 * Side effects:
 *	Allocates memory. Arbitrary, per the parent channel, and the called
 *	scripts.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideInt
ReflectSeekWide(
    ClientData clientData,
    Tcl_WideInt offset,
    int seekMode,
    int *errorCodePtr)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;
    Channel *parent = (Channel *) rtPtr->parent;
    Tcl_WideInt curPos;		/* Position on the device. */








|

|
|







1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
 * Side effects:
 *	Allocates memory. Arbitrary, per the parent channel, and the called
 *	scripts.
 *
 *----------------------------------------------------------------------
 */

static long long
ReflectSeekWide(
    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. */

1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static void
ReflectWatch(
    ClientData clientData,
    int mask)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;
    Tcl_DriverWatchProc *watchProc;

    watchProc = Tcl_ChannelWatchProc(Tcl_GetChannelType(rtPtr->parent));
    watchProc(Tcl_GetChannelInstanceData(rtPtr->parent), mask);







|







1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static void
ReflectWatch(
    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
 *
 * ReflectBlock --
 *
 *	This function is invoked to tell the channel which blocking behaviour
 *	is required of it.
 *
 * Results:
 *	A posix error number.
 *
 * Side effects:
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectBlock(
    ClientData 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







|









|







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
 *
 * ReflectBlock --
 *
 *	This function is invoked to tell the channel which blocking behaviour
 *	is required of it.
 *
 * Results:
 *	A Posix error number.
 *
 * Side effects:
 *	Allocates memory. Arbitrary, as it calls upon a script.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectBlock(
    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
 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectSetOption(
    ClientData 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;

    /*







|







1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectSetOption(
    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
 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectGetOption(
    ClientData 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 */
{
    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







|

|







1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectGetOption(
    void *clientData,	/* Channel to query */
    Tcl_Interp *interp,		/* Interpreter to leave error messages in */
    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
 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectHandle(
    ClientData clientData,
    int direction,
    ClientData *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
     * 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.
     */








|

|





|







1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectHandle(
    void *clientData,
    int direction,
    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 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
 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectNotify(
    ClientData clientData,
    int mask)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    /*
     * An event occured 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).
     */








|





|







1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
 *	Arbitrary, per the parent channel.
 *
 *----------------------------------------------------------------------
 */

static int
ReflectNotify(
    void *clientData,
    int mask)
{
    ReflectedTransform *rtPtr = (ReflectedTransform *)clientData;

    /*
     * 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).
     */

1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
    Tcl_Interp *interp,
    Tcl_Obj *cmdpfxObj,
    TCL_UNUSED(int) /*mode*/,
    Tcl_Obj *handleObj,
    Tcl_Channel parentChan)
{
    ReflectedTransform *rtPtr;
    int 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;







|

<







1715
1716
1717
1718
1719
1720
1721
1722
1723

1724
1725
1726
1727
1728
1729
1730
    Tcl_Interp *interp,
    Tcl_Obj *cmdpfxObj,
    TCL_UNUSED(int) /*mode*/,
    Tcl_Obj *handleObj,
    Tcl_Channel parentChan)
{
    ReflectedTransform *rtPtr;
    Tcl_Size i, listc;
    Tcl_Obj **listv;


    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

    /*
     * Method placeholder.
     */

    /* ASSERT: cmdpfxObj is a Tcl List */

    Tcl_ListObjGetElements(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] |







|







1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766

    /*
     * Method placeholder.
     */

    /* ASSERT: cmdpfxObj is a Tcl List */

    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
    Tcl_DecrRefCount(rtPtr->argv[n+1]);

    rtPtr->argc = 1;
}

static void
FreeReflectedTransform(
    ReflectedTransform *rtPtr)
{

    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
 *	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:







|

>















|







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
    Tcl_DecrRefCount(rtPtr->argv[n+1]);

    rtPtr->argc = 1;
}

static void
FreeReflectedTransform(
    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, 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
    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. */

    if (rtPtr->dead) {
	/*
	 * The transform is marked as dead. Bail out immediately, with an
	 * appropriate error.
	 */








|
|







1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
    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 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
     * 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,
     * before the channel id.
     */

    methObj = Tcl_NewStringObj(method, -1);
    Tcl_IncrRefCount(methObj);
    rtPtr->argv[rtPtr->argc - 2] = methObj;








|







1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
     * 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 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
	if (argTwoObj) {
	    rtPtr->argv[cmdc] = argTwoObj;
	    cmdc++;
	}
    }

    /*
     * And run the handler... This is done in auch 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);







|







1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
	if (argTwoObj) {
	    rtPtr->argv[cmdc] = argTwoObj;
	    cmdc++;
	}
    }

    /*
     * 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
	     * 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;
		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);







|







2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
	     * 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);
		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);
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
 *	registered in this interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteReflectedTransformMap(
    ClientData 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;


#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







|










>
>







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
 *	registered in this interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteReflectedTransformMap(
    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
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
 *	Deletes the hash table of channels.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteThreadReflectedTransformMap(
    TCL_UNUSED(ClientData))
{
    Tcl_HashSearch hSearch;	 /* Search variable. */
    Tcl_HashEntry *hPtr;	 /* Search variable. */
    Tcl_ThreadId self = Tcl_GetCurrentThread();
    ReflectedTransformMap *rtmPtr; /* The map */
    ForwardingResult *resultPtr;








|







2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
 *	Deletes the hash table of channels.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteThreadReflectedTransformMap(
    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

    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);

    /*
     * (*) Block until the other thread has either processed the transfer or
     * rejected it.
     */

    while (resultPtr->result < 0) {







|
|







2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426

    Tcl_CreateThreadExitHandler(SrcExitProc, evPtr);

    /*
     * Queue the event and poke the other thread's notifier.
     */

    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) {
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
	    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 */
	    unsigned char *bytev;
				/* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);

	    paramPtr->transform.size = bytec;

	    if (bytec > 0) {
		paramPtr->transform.buf = (char *)Tcl_Alloc(bytec);
		memcpy(paramPtr->transform.buf, bytev, bytec);
	    } else {







|



|







2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
	    paramPtr->transform.size = TCL_INDEX_NONE;
	} else {
	    /*
	     * Process a regular return. Contains the transformation result.
	     * Sent it back to the request originator.
	     */

	    Tcl_Size bytec = 0;	/* Number of returned bytes */
	    unsigned char *bytev;
				/* Array of returned bytes */

	    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
	    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 */
	    unsigned char *bytev;
				/* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);

	    paramPtr->transform.size = bytec;

	    if (bytec > 0) {
		paramPtr->transform.buf = (char *)Tcl_Alloc(bytec);
		memcpy(paramPtr->transform.buf, bytev, bytec);
	    } else {







|



|







2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
	    paramPtr->transform.size = TCL_INDEX_NONE;
	} else {
	    /*
	     * Process a regular return. Contains the transformation result.
	     * Sent it back to the request originator.
	     */

	    Tcl_Size bytec = 0;	/* Number of returned bytes */
	    unsigned char *bytev;
				/* Array of returned bytes */

	    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
	    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 */
	    unsigned char *bytev; /* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);

	    paramPtr->transform.size = bytec;

	    if (bytec > 0) {
		paramPtr->transform.buf = (char *)Tcl_Alloc(bytec);
		memcpy(paramPtr->transform.buf, bytev, bytec);
	    } else {







|


|







2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
	    paramPtr->transform.size = TCL_INDEX_NONE;
	} else {
	    /*
	     * Process a regular return. Contains the transformation result.
	     * Sent it back to the request originator.
	     */

	    Tcl_Size bytec = 0;	/* Number of returned bytes */
	    unsigned char *bytev; /* Array of returned bytes */

	    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
	    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 */
	    unsigned char *bytev;
				/* Array of returned bytes */

	    bytev = TclGetByteArrayFromObj(resObj, &bytec);

	    paramPtr->transform.size = bytec;

	    if (bytec > 0) {
		paramPtr->transform.buf = (char *)Tcl_Alloc(bytec);
		memcpy(paramPtr->transform.buf, bytev, bytec);
	    } else {







|



|







2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
	    paramPtr->transform.size = TCL_INDEX_NONE;
	} else {
	    /*
	     * Process a regular return. Contains the transformation result.
	     * Sent it back to the request originator.
	     */

	    Tcl_Size bytec = 0;	/* Number of returned bytes */
	    unsigned char *bytev;
				/* Array of returned bytes */

	    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
    }

    return 1;
}

static void
SrcExitProc(
    ClientData clientData)
{
    ForwardingEvent *evPtr = (ForwardingEvent *)clientData;
    ForwardingResult *resultPtr;
    ForwardParam *paramPtr;

    /*
     * NOTE (2): Can this handler be called with the originator blocked?







|







2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
    }

    return 1;
}

static void
SrcExitProc(
    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
}

static void
ForwardSetObjError(
    ForwardParam *paramPtr,
    Tcl_Obj *obj)
{
    size_t len;
    const char *msgStr = TclGetStringFromObj(obj, &len);

    len++;
    ForwardSetDynamicError(paramPtr, Tcl_Alloc(len));
    memcpy(paramPtr->base.msgStr, msgStr, len);
}
#endif /* TCL_THREADS */







|







2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
}

static void
ForwardSetObjError(
    ForwardParam *paramPtr,
    Tcl_Obj *obj)
{
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TimerRun(
    ClientData 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.
 *
 * Side effects:
 *	See above.
 *
 * Result:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ResultInit(
    ResultBuffer *rPtr)		/* Reference to the structure to
				 * initialize. */
{
    rPtr->used = 0;
    rPtr->allocated = 0;
    rPtr->buf = NULL;







|













|










|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
TimerRun(
    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 empty buffer.
 *
 * Side effects:
 *	See above.
 *
 * Result:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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
 *
 * Result:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ResultClear(
    ResultBuffer *rPtr)		/* Reference to the buffer to clear out */
{
    rPtr->used = 0;

    if (!rPtr->allocated) {
	return;







|







2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
 *
 * Result:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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
 *
 * Result:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ResultAdd(
    ResultBuffer *rPtr,		/* The buffer to extend */
    unsigned char *buf,		/* The buffer to read from */
    int 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.
	 */








|



|







2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
 *
 * Result:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static inline void
ResultAdd(
    ResultBuffer *rPtr,		/* The buffer to extend */
    unsigned char *buf,		/* The buffer to read from */
    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
 *
 * Result:
 *	The number of actually copied bytes, possibly less than 'toRead'.
 *
 *----------------------------------------------------------------------
 */

static int
ResultCopy(
    ResultBuffer *rPtr,		/* The buffer to read from */
    unsigned char *buf,		/* The buffer to copy into */
    int toRead)			/* Number of requested bytes */
{
    int copied;

    if (rPtr->used == 0) {
	/*
	 * Nothing to copy in the case of an empty buffer.
	 */







|



|







2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
 *
 * Result:
 *	The number of actually copied bytes, possibly less than 'toRead'.
 *
 *----------------------------------------------------------------------
 */

static inline size_t
ResultCopy(
    ResultBuffer *rPtr,		/* The buffer to read from */
    unsigned char *buf,		/* The buffer to copy into */
    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
static int
TransformRead(
    ReflectedTransform *rtPtr,
    int *errorCodePtr,
    Tcl_Obj *bufObj)
{
    Tcl_Obj *resObj;
    size_t 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.size));

	ForwardOpToOwnerThread(rtPtr, ForwardedInput, &p);

	if (p.base.code != TCL_OK) {
	    PassReceivedError(rtPtr->chan, &p);
	    *errorCodePtr = EINVAL;







|










|







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
static int
TransformRead(
    ReflectedTransform *rtPtr,
    int *errorCodePtr,
    Tcl_Obj *bufObj)
{
    Tcl_Obj *resObj;
    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 *) 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
    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);
    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 */
    unsigned char *bytev;	/* Array of returned bytes */
    int res;

    /*
     * Are we in the correct thread?
     */








|















|







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
    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 = 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;
    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
	    Tcl_DecrRefCount(bufObj);
	    Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
	    return 0;
	}

	*errorCodePtr = EOK;

	bytev = TclGetByteArrayFromObj(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 */
    unsigned char *bytev;	/* Array of returned bytes */

    /*
     * Are we in the correct thread?
     */

#if TCL_THREADS







|




















|







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
	    Tcl_DecrRefCount(bufObj);
	    Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
	    return 0;
	}

	*errorCodePtr = EOK;

	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;
    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
	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);
	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 */
    unsigned char *bytev;	/* Array of returned bytes */
    int res;

    /*
     * Are we in the correct thread?
     */








|
















|







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
	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 = 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;
    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
	    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);
	    res = Tcl_WriteRaw(rtPtr->parent, (char *) bytev, bytec);
	} else {
	    res = 0;
	}
	Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
    }








|







3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
	    Tcl_SetChannelError(rtPtr->chan, resObj);
	    Tcl_DecrRefCount(resObj);	/* Remove reference held from invoke */
	    *errorCodePtr = EINVAL;
	    return 0;
	}

	if (op == FLUSH_WRITE) {
	    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
/*
 * tclIOSock.c --
 *
 *	Common routines used by all socket based channel types.
 *
 * Copyright (c) 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"






|







1
2
3
4
5
6
7
8
9
10
11
12
13
/*
 * tclIOSock.c --
 *
 *	Common routines used by all socket based channel types.
 *
 * 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"

71
72
73
74
75
76
77
78




79
80
81
82
83
84
85
    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);




	sp = getservbyname(native, proto);		/* INTL: Native. */
	Tcl_DStringFree(&ds);
	if (sp != NULL) {
	    *portPtr = ntohs((unsigned short) sp->s_port);
	    return TCL_OK;
	}
    }







|
>
>
>
>







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
    const char *native;

    if (Tcl_GetInt(NULL, string, portPtr) != TCL_OK) {
	/*
	 * Don't bother translating 'proto' to native.
	 */

	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
#if !defined(_WIN32) && !defined(__CYGWIN__)
#   define SOCKET int
#endif

int
TclSockMinimumBuffers(
    void *sock,			/* Socket file descriptor */
    int size)			/* Minimum buffer size */
{
    int current;
    socklen_t len;





    len = sizeof(int);
    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,
		(char *) &size, len);







|



>

>
>
>







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#if !defined(_WIN32) && !defined(__CYGWIN__)
#   define SOCKET int
#endif

int
TclSockMinimumBuffers(
    void *sock,			/* Socket file descriptor */
    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,
	    (char *) &current, &len);
    if (current < size) {
	len = sizeof(int);
	setsockopt((SOCKET)(size_t) sock, SOL_SOCKET, SO_SNDBUF,
		(char *) &size, len);
176
177
178
179
180
181
182
183




184
185
186
187
188
189
190
    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);




    }

    /*
     * Workaround for OSX's apparent inability to resolve "localhost", "0"
     * when the loopback device is the only available network interface.
     */








|
>
>
>
>







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    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) {
	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.
     */

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

Tcl_Channel
Tcl_OpenTcpServer(
    Tcl_Interp *interp,
    int port,
    const char *host,
    Tcl_TcpAcceptProc *acceptProc,
    ClientData callbackData)
{
    char portbuf[TCL_INTEGER_SPACE];

    TclFormatInt(portbuf, port);
    return Tcl_OpenTcpServerEx(interp, portbuf, host, TCL_TCPSERVER_REUSEADDR,
	    acceptProc, callbackData);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|




|
|









321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343

Tcl_Channel
Tcl_OpenTcpServer(
    Tcl_Interp *interp,
    int port,
    const char *host,
    Tcl_TcpAcceptProc *acceptProc,
    void *callbackData)
{
    char portbuf[TCL_INTEGER_SPACE];

    TclFormatInt(portbuf, port);
    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
/*
 * 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.
 *
 * 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 _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
				 * (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









|
|
|






>


















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*
 * 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 © 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 {
    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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
				 * 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.
				 */
    ClientData cwdClientData;
    FilesystemRecord *filesystemList;
    size_t claims;
} ThreadSpecificData;

/*
 * Forward declarations.
 */

static Tcl_NRPostProc	EvalFileCallback;
static FilesystemRecord*FsGetFirstFilesystem(void);
static void		FsThrExitProc(ClientData 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		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);







|










|




|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
				 * 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.
				 */
    void *cwdClientData;
    FilesystemRecord *filesystemList;
    size_t claims;
} ThreadSpecificData;

/*
 * Forward declarations.
 */

static Tcl_NRPostProc	EvalFileCallback;
static FilesystemRecord*FsGetFirstFilesystem(void);
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, 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);
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    (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
 * uses of Tcl that provide no native filesystem.
 */

static FilesystemRecord nativeFilesystemRecord = {
    NULL,
    &tclNativeFilesystem,
    NULL,







|







175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
    (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 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

/*
 * 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;
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;
} FsDivertLoad;

/*
 * Obsolete string-based APIs that should be removed in a future release,
 * perhaps in Tcl 9.
 */








|

















|







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241

/*
 * 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 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;
    void *divertedFileNativeRep;
} FsDivertLoad;

/*
 * Obsolete string-based APIs that should be removed in a future release,
 * perhaps in Tcl 9.
 */

289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
	}

#   undef OUT_OF_RANGE
#   undef OUT_OF_URANGE
#endif /* !TCL_WIDE_INT_IS_LONG */

	/*
	 * Copy across all supported fields, with possible type coercions 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;







|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
	}

#   undef OUT_OF_RANGE
#   undef OUT_OF_URANGE
#endif /* !TCL_WIDE_INT_IS_LONG */

	/*
	 * 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;
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424

/*
 * The basic filesystem implementation.
 */

static void
FsThrExitProc(
    ClientData cd)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)cd;
    FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL;

    /*
     * Discard the cwd copy.
     */







|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425

/*
 * The basic filesystem implementation.
 */

static void
FsThrExitProc(
    void *cd)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)cd;
    FilesystemRecord *fsRecPtr = NULL, *tmpFsRecPtr = NULL;

    /*
     * Discard the cwd copy.
     */
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
    if (pathPtrPtr == NULL) {
	return (tsdPtr->cwdPathPtr == NULL);
    }

    if (tsdPtr->cwdPathPtr == *pathPtrPtr) {
	return 1;
    } else {
	size_t 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







|







518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
    if (pathPtrPtr == NULL) {
	return (tsdPtr->cwdPathPtr == NULL);
    }

    if (tsdPtr->cwdPathPtr == *pathPtrPtr) {
	return 1;
    } else {
	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
/*
 * If non-NULL, take posession of clientData and free it later.
 */

static void
FsUpdateCwd(
    Tcl_Obj *cwdObj,
    ClientData clientData)
{
    size_t len = 0;
    const char *str = NULL;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&fsDataKey);

    if (cwdObj != NULL) {
	str = TclGetStringFromObj(cwdObj, &len);
    }








|

|







658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
/*
 * If non-NULL, take posession of clientData and free it later.
 */

static void
FsUpdateCwd(
    Tcl_Obj *cwdObj,
    void *clientData)
{
    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
    }

    /*
     * Remove all filesystems, freeing any allocated memory that is no longer
     * needed.
     */


    fsRecPtr = filesystemList;
    while (fsRecPtr != NULL) {
	FilesystemRecord *tmpFsRecPtr = fsRecPtr->nextPtr;

	/*
	 * The native filesystem is static, so don't free it.
	 */







>







758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
    }

    /*
     * 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
 *	registered filesystems.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FSRegister(
    ClientData 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;
    }







|







841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
 *	registered filesystems.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_FSRegister(
    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
				 * 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;


    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.







|
>







987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
				 * 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;
    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
	if (ret == TCL_OK) {
	    FsAddMountsToGlobResult(tmpResultPtr, cwd, pattern, types);

	    /*
	     * resultPtr and tmpResultPtr are guaranteed to be distinct.
	     */

	    ret = Tcl_ListObjGetElements(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);







|







1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
	if (ret == TCL_OK) {
	    FsAddMountsToGlobResult(tmpResultPtr, cwd, pattern, types);

	    /*
	     * resultPtr and tmpResultPtr are guaranteed to be distinct.
	     */

	    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);
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
				 * 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.
				 */
{
    int 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) {
	goto endOfMounts;
    }
    if (Tcl_ListObjLength(NULL, resultPtr, &gLength) != TCL_OK) {
	goto endOfMounts;
    }
    for (i=0 ; i<mLength ; i++) {
	Tcl_Obj *mElt;
	int j;
	int found = 0;

	Tcl_ListObjIndex(NULL, mounts, i, &mElt);

	for (j=0 ; j<gLength ; j++) {
	    Tcl_Obj *gElt;








|







|


|




|







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
				 * 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.
				 */
{
    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 (TclListObjLength(NULL, mounts, &mLength) != TCL_OK || mLength == 0) {
	goto endOfMounts;
    }
    if (TclListObjLength(NULL, resultPtr, &gLength) != TCL_OK) {
	goto endOfMounts;
    }
    for (i=0 ; i<mLength ; i++) {
	Tcl_Obj *mElt;
	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
		    gLength--;
		}
		break;		/* Break out of for loop. */
	    }
	}
	if (!found && dir) {
	    Tcl_Obj *norm;
	    size_t 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.
	     */








|







1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
		    gLength--;
		}
		break;		/* Break out of for loop. */
	    }
	}
	if (!found && dir) {
	    Tcl_Obj *norm;
	    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.
	     */

1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
 *	(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,
 *	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.







|
<
<







1211
1212
1213
1214
1215
1216
1217
1218


1219
1220
1221
1222
1223
1224
1225
 *	(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.


 *
 *	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.
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
Tcl_FSData(
    const Tcl_Filesystem *fsPtr) /* The filesystem to find in the list of
				  *  registered filesystems. */
{
    ClientData retVal = NULL;
    FilesystemRecord *fsRecPtr = FsGetFirstFilesystem();

    /*
     * Find the filesystem in and retrieve its clientData.
     */

    while ((retVal == NULL) && (fsRecPtr != NULL)) {







|




|







1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
Tcl_FSData(
    const Tcl_Filesystem *fsPtr) /* The filesystem to find in the list of
				  *  registered filesystems. */
{
    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
 *	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 ../, ./
 *	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;
    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;

	}

	--i;
	if (path[i] == ':') isVfsPath = 1;


    }

    /*
     * Call the the normalizePathProc routine of each registered filesystem.
     */
    firstFsRecPtr = FsGetFirstFilesystem();








|




















|














|
|
|
|
>
>
|
>
|
>

|
>
>







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
 *	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 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;

    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;
	    }
	}
	--i;
	if (path[i] == ':') {
	    isVfsPath = 1;
	}
    }

    /*
     * Call the the normalizePathProc routine of each registered filesystem.
     */
    firstFsRecPtr = FsGetFirstFilesystem();

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
}

/*
 *---------------------------------------------------------------------------
 *
 * 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
 *	seek to EOF after opening the file, or to 0 otherwise.
 *

 *	Sets *binaryPtr to 1 to tell the caller to configure the channel as a
 *	binary channel, or to 0 otherwise.
 *
 *	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(
    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
				 * configure the channel for binary
				 * operations after opening the file. */
{
    int mode, modeArgc, c, i, gotRW;

    const char **modeArgv, *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;

    /*
     * 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;
	    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 |= O_RDWR;
		break;
	    case 'b':
		*binaryPtr = 1;
		break;
	    default:
		goto error;
	    }
	}
	if (modeString[i] != 0) {
	    goto error;
	}
	return mode;

    error:
	*seekFlagPtr = 0;
	*binaryPtr = 0;
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "illegal access mode \"%s\"", modeString));

	}
	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) {

	if (interp != NULL) {
	    Tcl_AddErrorInfo(interp,
		    "\n    while processing open access modes \"");
	    Tcl_AddErrorInfo(interp, modeString);
	    Tcl_AddErrorInfo(interp, "\"");




	}
	return -1;
    }

    gotRW = 0;
    for (i = 0; i < modeArgc; i++) {
	flag = modeArgv[i];
	c = flag[0];
	if ((c == 'R') && (strcmp(flag, "RDONLY") == 0)) {









	    mode = (mode & ~RW_MODES) | O_RDONLY;
	    gotRW = 1;
	} else if ((c == 'W') && (strcmp(flag, "WRONLY") == 0)) {



	    mode = (mode & ~RW_MODES) | O_WRONLY;
	    gotRW = 1;
	} else if ((c == 'R') && (strcmp(flag, "RDWR") == 0)) {



	    mode = (mode & ~RW_MODES) | O_RDWR;
	    gotRW = 1;
	} else if ((c == 'A') && (strcmp(flag, "APPEND") == 0)) {








	    mode |= O_APPEND;
	    *seekFlagPtr = 1;
	} else if ((c == 'C') && (strcmp(flag, "CREAT") == 0)) {



	    mode |= O_CREAT;
	} else if ((c == 'E') && (strcmp(flag, "EXCL") == 0)) {
	    mode |= O_EXCL;



	} else if ((c == 'N') && (strcmp(flag, "NOCTTY") == 0)) {
#ifdef O_NOCTTY



	    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);
	    return -1;
#endif

	} else if ((c == 'N') && (strcmp(flag, "NONBLOCK") == 0)) {
#ifdef O_NONBLOCK



	    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);
	    return -1;
#endif

	} else if ((c == 'T') && (strcmp(flag, "TRUNC") == 0)) {



	    mode |= O_TRUNC;
	} else if ((c == 'B') && (strcmp(flag, "BINARY") == 0)) {



	    *binaryPtr = 1;
	} 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));
	    }
	    Tcl_Free((void *)modeArgv);
	    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",
		    -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.
 *
 *	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.
 *







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






|


>
|
<

|
|








|



<
<
|
<
<

|
>
|
<







<
|
|









<











|
















|
<


|











<
|



>











>





>
>
>
>









>
>
>
>
>
>
>
>
>
|


>
>
>
|


>
>
>
|


>
>
>
>
>
>
>
>

|

>
>
>


|
>
|
>


>
>
>







|
<




>
>
>







|
<

<

>
>
>


>
>
>
|

<


|
|
|

|
<








|














|







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 --
 *































 *	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 *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
 *	to configure the channel as a binary channel.

 *
 *	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
TclGetOpenMode(
    Tcl_Interp *interp,		/* Interpreter, possibly NULL, to use for
				 * error reporting. */
    const char *modeString,	/* Mode string, e.g. "r+" or "RDONLY CREAT" */


    int *modeFlagsPtr)


{
    int mode, c, gotRW;
    Tcl_Size modeArgc, i;
    const char **modeArgv = NULL, *flag;


    /*
     * 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.
     */


    *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':

	    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;
	    *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 = (mode & ~(O_ACCMODE|O_APPEND)) | O_RDWR;

		break;
	    case 'b':
		*modeFlagsPtr |= CHANNEL_RAW_MODE;
		break;
	    default:
		goto error;
	    }
	}
	if (modeString[i] != 0) {
	    goto error;
	}
	return mode;

    error:

	*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 & ~O_ACCMODE) | O_RDONLY;
	    gotRW = 1;
	} else if ((c == 'W') && (strcmp(flag, "WRONLY") == 0)) {
	    if (gotRW) {
		goto invRW;
	    }
	    mode = (mode & ~O_ACCMODE) | O_WRONLY;
	    gotRW = 1;
	} else if ((c == 'R') && (strcmp(flag, "RDWR") == 0)) {
	    if (gotRW) {
		goto invRW;
	    }
	    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;
	    *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)) {
	    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));
	    }
	    goto invAccessMode;

#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));
	    }
	    goto invAccessMode;

#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;
	    }
	    *modeFlagsPtr |= CHANNEL_RAW_MODE;
	} else {

	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"invalid access mode \"%s\": must be APPEND, BINARY, "
			"CREAT, EXCL, NOCTTY, NONBLOCK, RDONLY, RDWR, "
			"TRUNC, or WRONLY", flag));
	    }
	    goto invAccessMode;

	}
    }

    Tcl_Free((void *)modeArgv);

    if (!gotRW) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "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 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.
 *
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
    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. */
{
    size_t length;
	int result = TCL_ERROR;
    Tcl_StatBuf statBuf;
    Tcl_Obj *oldScriptFile;
    Interp *iPtr;
    const char *string;
    Tcl_Channel chan;
    Tcl_Obj *objPtr;








|
|







1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
    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. */
{
    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
	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]
     */

    Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");

    /*
     * 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) {







|
|


|







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 \x1A (^Z). Tcl uses it on every platform to allow
     * for scripted documents. [Bug: 2040]
     */

    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
    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) {
	Tcl_CloseEx(interp, chan, 0);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't read file \"%s\": %s",
		TclGetString(pathPtr), Tcl_PosixError(interp)));
	goto end;
    }








|
|







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, 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
	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 overflow = (length > limit);

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (file \"%.*s%s\" line %d)",
		(overflow ? limit : (unsigned)length), pathString,
		(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
    }

  end:
    Tcl_DecrRefCount(objPtr);
    return result;
}







|




|







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);
	int limit = 150;
	int overflow = (length > limit);

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (file \"%.*s%s\" line %d)",
		(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
		"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]
     */

    Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");

    /*
     * 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) {







|
|


|







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 \x1A (^Z). Tcl uses it on every platform to allow
     * for scripted documents. [Bug: 2040]
     */

    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
    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) {
	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;
    }







|
|







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, 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
    TclNRAddCallback(interp, EvalFileCallback, oldScriptFile, pathPtr, objPtr,
	    NULL);
    return TclNREvalObjEx(interp, objPtr, 0, NULL, INT_MIN);
}

static int
EvalFileCallback(
    ClientData 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];







|







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(
    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
    if (result == TCL_RETURN) {
	result = TclUpdateReturnInfo(iPtr);
    } else if (result == TCL_ERROR) {
	/*
	 * Record information about where the error occurred.
	 */

	size_t length;
	const char *pathString = TclGetStringFromObj(pathPtr, &length);
	const unsigned 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 ? "..." : ""), Tcl_GetErrorLine(interp)));
    }

    Tcl_DecrRefCount(objPtr);
    return result;
}








|

|




|







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.
	 */

	Tcl_Size length;
	const char *pathString = TclGetStringFromObj(pathPtr, &length);
	const int limit = 150;
	int overflow = (length > limit);

	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (file \"%.*s%s\" line %d)",
		(overflow ? limit : (int)length), pathString,
		(overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
    }

    Tcl_DecrRefCount(objPtr);
    return result;
}

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
    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);
    }
    return msg;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FSStat --
 *	Calls 'statProc' of the filesystem corresponding to pathPtr.
 *
 *	Replaces the standard library routines stat.
 *
 *
 * Results:
 *	See stat documentation.
 *
 * Side effects:
 *	See stat documentation.
 *







|










|
<







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
    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, (char *)NULL);
    }
    return msg;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FSStat --
 *	Calls 'statProc' of the filesystem corresponding to pathPtr.
 *
 *	Replaces the standard library "stat" routine.

 *
 * Results:
 *	See stat documentation.
 *
 * Side effects:
 *	See stat documentation.
 *
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
	 * Return the correct error message.
	 */
	return NULL;
    }

    fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
    if (fsPtr != NULL && fsPtr->openFileChannelProc != NULL) {
	int mode, seekFlag, binary;

	/*
	 * 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);
	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)
		< (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) {
	    Tcl_SetChannelOption(interp, retVal, "-translation", "binary");
	}
	return retVal;
    }

    /*
     * File doesn't belong to any filesystem that can open it.







|






|


















|









|







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
	 * Return the correct error message.
	 */
	return NULL;
    }

    fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
    if (fsPtr != NULL && fsPtr->openFileChannelProc != NULL) {
	int mode, modeFlags;

	/*
	 * Parse the mode to determine whether to seek at the outset
	 * and/or set the channel into binary mode.
	 */

	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 ((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 (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
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);





    if (fsPtr != NULL && fsPtr->utimeProc != NULL) {
	return fsPtr->utimeProc(pathPtr, tval);
    }


    /* TODO: set errno here? Tcl_SetErrno(ENOENT); */
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * NativeFileAttrStrings --







>

>
>
>
|
|
|
>
>
|







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
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->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
	}
	return result;
    } else if (listObj != NULL) {
	/*
	 * It's a non-constant attribute list, so do a literal search.
	 */

	int i, objc;
	Tcl_Obj **objv;

	if (Tcl_ListObjGetElements(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;







|


|







2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
	}
	return result;
    } else if (listObj != NULL) {
	/*
	 * It's a non-constant attribute list, so do a literal search.
	 */

	Tcl_Size i, objc;
	Tcl_Obj **objv;

	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
	 * current directory.
	 */

	fsRecPtr = FsGetFirstFilesystem();
	Claim();
	for (; (retVal == NULL) && (fsRecPtr != NULL);
		fsRecPtr = fsRecPtr->nextPtr) {
	    ClientData retCd;
	    TclFSGetCwdProc2 *proc2;

	    if (fsRecPtr->fsPtr->getCwdProc == NULL) {
		continue;
	    }

	    if (fsRecPtr->fsPtr->version == TCL_FILESYSTEM_VERSION_1) {







|







2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
	 * current directory.
	 */

	fsRecPtr = FsGetFirstFilesystem();
	Claim();
	for (; (retVal == NULL) && (fsRecPtr != NULL);
		fsRecPtr = fsRecPtr->nextPtr) {
	    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
		 */

		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.

		     *
		     * 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.







|
|
>







2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
		 */

		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.
		     *
		     * 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
	 * 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;
	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.
	     */







|







2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
	 * 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);
	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.
	     */
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
	     * 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;
	    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







|







2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
	     * 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.
	     */

	    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
	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;

	    /*
	     * Assume that the native filesystem has a getCwdProc and that it
	     * is at version 2.
	     */

	    TclFSGetCwdProc2 *proc2 = (TclFSGetCwdProc2 *) fsPtr->getCwdProc;







|
|







2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
	if (normDirName == NULL) {
	    /* Not really true, but what else to do? */
	    Tcl_SetErrno(ENOENT);
	    return -1;
	}

	if (fsPtr == &tclNativeFilesystem) {
	    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;
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
Tcl_FSLoadFile(
    Tcl_Interp *interp,		/* Used for error reporting. */
    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,
				/* 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];
    } else {
	*proc1Ptr = *proc2Ptr = NULL;
    }

    return res;
}








|

















|
|







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
Tcl_FSLoadFile(
    Tcl_Interp *interp,		/* Used for error reporting. */
    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_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_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
 * 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
 *
 */








static int
skipUnlink(
    Tcl_Obj *shlibFile)
{
    /*
     * Unlinking is not performed in the following cases:







>
>
>
>
>
>
>







3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
 * 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:
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
     */


#ifdef hpux
    (void)shlibFile;
    return 1;
#else
    char *skipstr = getenv("TCL_TEMPLOAD_NO_UNLINK");

    if (skipstr && (skipstr[0] != '\0')) {
	return atoi(skipstr);
    }

#ifndef TCL_TEMPLOAD_NO_UNLINK
    (void)shlibFile;







|







3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
     */


#ifdef hpux
    (void)shlibFile;
    return 1;
#else
    WCHAR *skipstr = getenv("TCL_TEMPLOAD_NO_UNLINK");

    if (skipstr && (skipstr[0] != '\0')) {
	return atoi(skipstr);
    }

#ifndef TCL_TEMPLOAD_NO_UNLINK
    (void)shlibFile;
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
	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







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







3613
3614
3615
3616
3617
3618
3619





















































































3620
3621
3622
3623
3624
3625
3626
	return TCL_ERROR;
    }
    if (handle->unloadFileProcPtr != NULL) {
	handle->unloadFileProcPtr(handle);
    }
    return TCL_OK;
}






















































































/*
 *---------------------------------------------------------------------------
 *
 * Tcl_FSLink --
 *
 *	Creates or inspects a link by calling 'linkProc' of the filesystem
3721
3722
3723
3724
3725
3726
3727
3728




3729

3730
3731
3732
3733
3734
3735
3736
    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 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.







|
>
>
>
>
|
>







3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
    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) {
	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
    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.  */

		Tcl_DecrRefCount(thisFsVolumes);
	    }
	}
	fsRecPtr = fsRecPtr->nextPtr;
    }
    Disclaim();








>
|
|
|
|
>







3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
    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.
		 */
		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
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_FSSplitPath(
    Tcl_Obj *pathPtr,		/* The pathname to split. */
    int *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;
    const char *p;

    /*
     * Perform platform-specific splitting.
     */

    if (TclFSGetPathType(pathPtr, &fsPtr,







|





|







3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_FSSplitPath(
    Tcl_Obj *pathPtr,		/* The pathname to split. */
    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 = '/';
    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

    /*
     * Add the remaining pathname elements to the list.
     */

    for (;;) {
	const char *elementStart = p;
	int 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);
	    }
	    Tcl_ListObjAppendElement(NULL, result, nextElt);
	}
	if (*p++ == '\0') {
	    break;
	}
    }








|







<
<
<
<
<
|
<







3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871





3872

3873
3874
3875
3876
3877
3878
3879

    /*
     * Add the remaining pathname elements to the list.
     */

    for (;;) {
	const char *elementStart = p;
	Tcl_Size length;

	while ((*p != '\0') && (*p != separator)) {
	    p++;
	}
	length = p - elementStart;
	if (length > 0) {
	    Tcl_Obj *nextElt;





	    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
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. */
    int *driveNameLengthPtr,	/* 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;
    const char *path = TclGetStringFromObj(pathPtr, &pathLen);
    Tcl_PathType type;

    type = TclFSNonnativePathType(path, pathLen, filesystemPtrPtr,
	    driveNameLengthPtr, driveNameRef);

    if (type != TCL_PATH_ABSOLUTE) {







|






|







3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
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,	/* 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. */
{
    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
 *
 *----------------------------------------------------------------------
 */

Tcl_PathType
TclFSNonnativePathType(
    const char *path,		/* Pathname to determine the type of. */
    int 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. */
    int *driveNameLengthPtr,	/* 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
				 * incremented, and contining the name of the
				 * volume if the pathname is absolute. */
{







|




|







3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
 *
 *----------------------------------------------------------------------
 */

Tcl_PathType
TclFSNonnativePathType(
    const char *path,		/* Pathname to determine the type of. */
    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,/* 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
				 * incremented, and contining the name of the
				 * volume if the pathname is absolute. */
{
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
	 * 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_Obj *thisFsVolumes = fsRecPtr->fsPtr->listVolumesProc();

	    if (thisFsVolumes != NULL) {
		if (Tcl_ListObjLength(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;
		}
		while (numVolumes > 0) {
		    Tcl_Obj *vol;
		    size_t len;
		    const char *strVol;

		    numVolumes--;
		    Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol);
		    strVol = TclGetStringFromObj(vol,&len);
		    if ((size_t) pathLen < len) {
			continue;
		    }
		    if (strncmp(strVol, path, len) == 0) {
			type = TCL_PATH_ABSOLUTE;
			if (filesystemPtrPtr != NULL) {
			    *filesystemPtrPtr = fsRecPtr->fsPtr;
			}







|



|










|



|





|







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
	 * 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)) {
	    Tcl_Size numVolumes;
	    Tcl_Obj *thisFsVolumes = fsRecPtr->fsPtr->listVolumesProc();

	    if (thisFsVolumes != NULL) {
		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 = TCL_INDEX_NONE;
		}
		while (numVolumes > 0) {
		    Tcl_Obj *vol;
		    Tcl_Size len;
		    const char *strVol;

		    numVolumes--;
		    Tcl_ListObjIndex(NULL, thisFsVolumes, numVolumes, &vol);
		    strVol = TclGetStringFromObj(vol,&len);
		    if (pathLen < len) {
			continue;
		    }
		    if (strncmp(strVol, path, len) == 0) {
			type = TCL_PATH_ABSOLUTE;
			if (filesystemPtrPtr != NULL) {
			    *filesystemPtrPtr = fsRecPtr->fsPtr;
			}
4296
4297
4298
4299
4300
4301
4302

4303



4304
4305
4306


4307
4308
4309
4310
4311
4312
4313
4314
 */

int
Tcl_FSDeleteFile(
    Tcl_Obj *pathPtr)		/* Pathname of file to be removed (UTF-8). */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);





    if (fsPtr != NULL && fsPtr->deleteFileProc != NULL) {
	return fsPtr->deleteFileProc(pathPtr);
    }


    Tcl_SetErrno(ENOENT);
    return -1;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_FSCreateDirectory --







>

>
>
>
|
|
|
>
>
|







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
 */

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->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
 */

int
Tcl_FSCreateDirectory(
    Tcl_Obj *pathPtr)		/* Pathname of directory to create (UTF-8). */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);





    if (fsPtr != NULL && fsPtr->createDirectoryProc != NULL) {
	return fsPtr->createDirectoryProc(pathPtr);
    }


    Tcl_SetErrno(ENOENT);
    return -1;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_FSCopyDirectory --







>

>
>
>
|
|
|
>
>
|







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
 */

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->createDirectoryProc != NULL) {
	    return fsPtr->createDirectoryProc(pathPtr);
	}
	err = ENOTSUP;
    }
    Tcl_SetErrno(err);
    return -1;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_FSCopyDirectory --
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
 *	copyDirectoryProc is found.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_FSCopyDirectory(
    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. */
{
    int retVal = -1;
    const Tcl_Filesystem *fsPtr, *fsPtr2;

    fsPtr = Tcl_FSGetFileSystemForPath(srcPathPtr);
    fsPtr2 = Tcl_FSGetFileSystemForPath(destPathPtr);








|
|
<


|
|
|
|







4305
4306
4307
4308
4309
4310
4311
4312
4313

4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
 *	copyDirectoryProc is found.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_FSCopyDirectory(
    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. */
{
    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
 *	removeDirectoryProc is found.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_FSRemoveDirectory(
    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
				 * object having a refCount of 1 and containing
				 * the name of the file that produced an error.
				 * */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);

    if (fsPtr == NULL || fsPtr->removeDirectoryProc == NULL) {
	Tcl_SetErrno(ENOENT);
	return -1;




    }

    if (recursive) {
	Tcl_Obj *cwdPtr = Tcl_FSGetCwd(NULL);
	if (cwdPtr != NULL) {
	    const char *cwdStr, *normPathStr;
	    size_t 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)) {







|
<






|
<



|


>
>
>
>






|







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
 *	removeDirectoryProc is found.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_FSRemoveDirectory(
    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
				 * object having a refCount of 1 and containing
				 * the name of the file that produced an error. */

{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);

    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;
	    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
    }

    /*
     * Call each of the "pathInFilesystem" functions in succession until the
     * corresponding filesystem is found.
     */
    for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) {
	ClientData 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







|







4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
    }

    /*
     * Call each of the "pathInFilesystem" functions in succession until the
     * corresponding filesystem is found.
     */
    for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) {
	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
 *	Memory is released.
 *
 *---------------------------------------------------------------------------
 */

static void
NativeFreeInternalRep(
    ClientData clientData)
{
    Tcl_Free(clientData);
}

/*
 *---------------------------------------------------------------------------
 *







|







4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
 *	Memory is released.
 *
 *---------------------------------------------------------------------------
 */

static void
NativeFreeInternalRep(
    void *clientData)
{
    Tcl_Free(clientData);
}

/*
 *---------------------------------------------------------------------------
 *

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
/*
 * 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.
 *
 * 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);
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,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		PrefixLongestObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		PrefixMatchObjCmd(ClientData clientData,
			    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 = {
    "index",			/* name */
    FreeIndex,			/* freeIntRepProc */
    DupIndex,			/* dupIntRepProc */
    UpdateStringOfIndex,	/* updateStringProc */
    NULL			/* setFromAnyProc */

};

/*
 * 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. */
} 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)

/*
 *----------------------------------------------------------------------
 *
 * GetIndexFromObjList --
 *
 *	This procedure looks up an object's value in a table of strings and







|
|
|













|



|
<
<
|
<
<
|
<
<








|




|
>












|
|











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


29


30


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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 © 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, 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 Tcl_ObjCmdProc PrefixAllObjCmd;


static Tcl_ObjCmdProc PrefixLongestObjCmd;


static Tcl_ObjCmdProc PrefixMatchObjCmd;


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.
 */

const Tcl_ObjType tclIndexType = {
    "index",			/* name */
    FreeIndex,			/* freeIntRepProc */
    DupIndex,			/* dupIntRepProc */
    UpdateStringOfIndex,	/* updateStringProc */
    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 */
    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) \
	(((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
    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. */
{


    int objc, result, t;
    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.
     */

    result = Tcl_ListObjGetElements(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);
	    *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);

    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
 *	be ...'
 *
 * Side effects:
 *	The result of the lookup is cached as the internal rep of objPtr, so
 *	that repeated lookups can be done quickly.
 *
 *----------------------------------------------------------------------
 */


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 */
    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 index, idx, numAbbrev;
    const char *key, *p1;
    const char *p2;
    const char *const *entryPtr;
    Tcl_Obj *resultPtr;
    IndexRep *indexRep;
    const Tcl_ObjIntRep *irPtr;

    /* Protect against invalid values, like -1 or 0. */
    if (offset+1 <= sizeof(char *)) {



	offset = sizeof(char *);


    }
    /*
     * 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;
	    return TCL_OK;

	}
    }
    }

    /*
     * Lookup the value of the object in the table. Accept unique
     * abbreviations unless TCL_EXACT is set in flags.
     */

    key = TclGetString(objPtr);
    index = -1;
    numAbbrev = 0;




    /*
     * 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;
	    entryPtr = NEXT_ENTRY(entryPtr, offset), idx++) {
	for (p1 = key, p2 = *entryPtr; *p1 == *p2; p1++, p2++) {
	    if (*p1 == '\0') {
		index = idx;
		goto done;
	    }
	}







|


>
|





|


|















|











|
















|
>
|
|
|
|









>









|


|
|

|





|

<
|
>
>
>
|
>
>





|
|
|
|
|
>
>
|
<
>
|
|







|
|


>
>
>







|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
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 */
    Tcl_Size *indexPtr)		/* Place to store resulting index. */
{

    Tcl_Size objc, 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 inefficient but simpler.
     */

    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(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(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
 *	(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. */
    Tcl_Size offset,		/* The number of bytes between entries */
    const char *msg,		/* Identifying word to use in error
				 * messages. */
    int flags,			/* 0, TCL_EXACT, TCL_NULL_OK or TCL_INDEX_TEMP_TABLE */
    void *indexPtr)		/* Place to store resulting index. */
{
    Tcl_Size index, idx, numAbbrev;
    const char *key, *p1;
    const char *p2;
    const char *const *entryPtr;
    Tcl_Obj *resultPtr;
    IndexRep *indexRep;
    const Tcl_ObjInternalRep *irPtr;


    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 (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;

		goto uncachedDone;
	    }
	}
    }

    /*
     * Lookup the value of the object in the table. Accept unique
     * abbreviations unless TCL_EXACT is set in flags.
     */

    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;
	    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
  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 (irPtr) {
	indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;
    } else {
	Tcl_ObjIntRep ir;

	indexRep = (IndexRep*)Tcl_Alloc(sizeof(IndexRep));
	ir.twoPtrValue.ptr1 = indexRep;
	Tcl_StoreIntRep(objPtr, &indexType, &ir);
    }
    indexRep->tablePtr = (void *) tablePtr;
    indexRep->offset = offset;
    indexRep->index = index;
    }



















    *indexPtr = index;

    return TCL_OK;

  error:
    if (interp != NULL) {
	/*
	 * Produce a fancy error message.
	 */

	int count = 0;

	TclNewObj(resultPtr);
	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);
	if (*entryPtr == NULL) {
	    Tcl_AppendStringsToObj(resultPtr, "\": no valid options", NULL);
	} else {
	    Tcl_AppendStringsToObj(resultPtr, "\": must be ",
		    *entryPtr, NULL);
	    entryPtr = NEXT_ENTRY(entryPtr, offset);
	    while (*entryPtr != NULL) {
		if (*NEXT_ENTRY(entryPtr, offset) == NULL) {
		    Tcl_AppendStringsToObj(resultPtr, (count > 0 ? "," : ""),
			    " or ", *entryPtr, NULL);
		} else if (**entryPtr) {
		    Tcl_AppendStringsToObj(resultPtr, ", ", *entryPtr, NULL);
		    count++;
		}
		entryPtr = NEXT_ENTRY(entryPtr, offset);
	    }


	}

	Tcl_SetObjResult(interp, resultPtr);
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INDEX", msg, key, NULL);
    }
    return TCL_ERROR;
}




/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfIndex --
 *
 *	This function is called to convert a Tcl object from index internal







|
|



|



|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>











|





|

|


|


|

|

|




>
>
|
>

|



>
>
>







278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 (objPtr && (index != TCL_INDEX_NONE) && !(flags & TCL_INDEX_TEMP_TABLE)) {
    irPtr = TclFetchInternalRep(objPtr, &tclIndexType);
    if (irPtr) {
	indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;
    } else {
	Tcl_ObjInternalRep ir;

	indexRep = (IndexRep*)Tcl_Alloc(sizeof(IndexRep));
	ir.twoPtrValue.ptr1 = indexRep;
	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;
	    }
	}
	*(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;
	while ((*entryPtr != NULL) && !**entryPtr) {
	    entryPtr = NEXT_ENTRY(entryPtr, offset);
	}
	Tcl_AppendStringsToObj(resultPtr,
		(numAbbrev>1 && !(flags & TCL_EXACT) ? "ambiguous " : "bad "),
		msg, " \"", key, (char *)NULL);
	if (*entryPtr == NULL) {
	    Tcl_AppendStringsToObj(resultPtr, "\": no valid options", (char *)NULL);
	} else {
	    Tcl_AppendStringsToObj(resultPtr, "\": must be ",
		    *entryPtr, (char *)NULL);
	    entryPtr = NEXT_ENTRY(entryPtr, offset);
	    while (*entryPtr != NULL) {
		if ((*NEXT_ENTRY(entryPtr, offset) == NULL) && !(flags & TCL_NULL_OK)) {
		    Tcl_AppendStringsToObj(resultPtr, (count > 0 ? "," : ""),
			    " or ", *entryPtr, (char *)NULL);
		} else if (**entryPtr) {
		    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, (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
 *----------------------------------------------------------------------
 */

static void
UpdateStringOfIndex(
    Tcl_Obj *objPtr)
{
    IndexRep *indexRep = (IndexRep *)TclFetchIntRep(objPtr, &indexType)->twoPtrValue.ptr1;
    const char *indexStr = EXPAND_OF(indexRep);

    Tcl_InitStringRep(objPtr, indexStr, strlen(indexStr));
}

/*
 *----------------------------------------------------------------------







|







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
 *----------------------------------------------------------------------
 */

static void
UpdateStringOfIndex(
    Tcl_Obj *objPtr)
{
    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
 */

static void
DupIndex(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dupPtr)
{
    Tcl_ObjIntRep ir;
    IndexRep *dupIndexRep = (IndexRep *)Tcl_Alloc(sizeof(IndexRep));

    memcpy(dupIndexRep, TclFetchIntRep(srcPtr, &indexType)->twoPtrValue.ptr1,
	    sizeof(IndexRep));

    ir.twoPtrValue.ptr1 = dupIndexRep;
    Tcl_StoreIntRep(dupPtr, &indexType, &ir);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeIndex --
 *







|


|



|







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_ObjInternalRep ir;
    IndexRep *dupIndexRep = (IndexRep *)Tcl_Alloc(sizeof(IndexRep));

    memcpy(dupIndexRep, TclFetchInternalRep(srcPtr, &tclIndexType)->twoPtrValue.ptr1,
	    sizeof(IndexRep));

    ir.twoPtrValue.ptr1 = dupIndexRep;
    Tcl_StoreInternalRep(dupPtr, &tclIndexType, &ir);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeIndex --
 *
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
 *----------------------------------------------------------------------
 */

static void
FreeIndex(
    Tcl_Obj *objPtr)
{
    Tcl_Free(TclFetchIntRep(objPtr, &indexType)->twoPtrValue.ptr1);
    objPtr->typePtr = NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitPrefixCmd --







|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
 *----------------------------------------------------------------------
 */

static void
FreeIndex(
    Tcl_Obj *objPtr)
{
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PrefixMatchObjCmd(
    TCL_UNUSED(ClientData),
    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;
    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
    };

    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) {
	    return TCL_ERROR;
	}
	switch ((enum matchOptionsEnum) 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);
		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);
		return TCL_ERROR;
	    }
	    i++;
	    result = Tcl_ListObjLength(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);
		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);
    if (result != TCL_OK) {
	return result;
    }

    result = GetIndexFromObjList(interp, objPtr, tablePtr, message, flags,
	    &index);
    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);
    if (result != TCL_OK) {
	return result;
    }
    Tcl_SetObjResult(interp, resultPtr);
    return TCL_OK;
}








|




|
|








|







|
|


|






|
|








|
|



|







|















|





|


















|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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_GetIndexFromObjStruct(interp, objv[i], matchOptions,
		sizeof(char *), "option", 0, &index) != TCL_OK) {
	    return TCL_ERROR;
	}
	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", 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", TCL_INDEX_NONE));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NOARG", (char *)NULL);
		return TCL_ERROR;
	    }
	    i++;
	    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", (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 = TclListObjLength(interp, tablePtr, &i);
    if (result != TCL_OK) {
	return result;
    }

    result = GetIndexFromObjList(interp, objPtr, tablePtr, message, flags,
	    &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, 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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PrefixAllObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int tableObjc, result, t;
    size_t length, elemLength;
    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);
    if (result != TCL_OK) {
	return result;
    }
    resultPtr = Tcl_NewListObj(0, NULL);
    string = TclGetStringFromObj(objv[2], &length);

    for (t = 0; t < tableObjc; t++) {







|




|
|








|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 = 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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PrefixLongestObjCmd(
    TCL_UNUSED(ClientData),
    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;
    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);
    if (result != TCL_OK) {
	return result;
    }
    string = TclGetStringFromObj(objv[2], &length);

    resultString = NULL;
    resultLength = 0;







|




|
|








|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 = 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

	    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],
			    resultString) - resultString;
		    break;
		}
	    }
	}
    }
    if (resultLength > 0) {







|







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 = 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
 *
 *----------------------------------------------------------------------
 */

void
Tcl_WrongNumArgs(
    Tcl_Interp *interp,		/* Current interpreter. */
    int 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;
    char flags;
    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);
    } else {
	Tcl_AppendToObj(objPtr, "wrong # args: should be \"", -1);
    }

    /*
     * 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 (iPtr->ensembleRewrite.sourceObjs != NULL) {
	int toSkip = iPtr->ensembleRewrite.numInsertedObjs;
	int toPrint = iPtr->ensembleRewrite.numRemovedObjs;
	Tcl_Obj *const *origObjv = iPtr->ensembleRewrite.sourceObjs;

	/*
	 * 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
	 * actually arguments (in objv) to this function. Otherwise it just
	 * gets too complicated and we'd be better off just giving 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.
	 */

	for (i=0 ; i<toPrint ; i++) {
	    /*
	     * Add the element, quoting it if necessary.
	     */
	    const Tcl_ObjIntRep *irPtr;

	    if ((irPtr = TclFetchIntRep(origObjv[i], &indexType))) {
		IndexRep *indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;

		elementStr = EXPAND_OF(indexRep);
		elemLen = strlen(elementStr);
	    } else {
		elementStr = TclGetStringFromObj(origObjv[i], &elemLen);
	    }







|







<
|

|






|

|



|
|



|
|
|


<
<
<
<
<
<
<
<
|

|















|






|

|







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. */
    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;

    Tcl_Size i, len, elemLen;
    char flags;
    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 \"", TCL_INDEX_NONE);
    } else {
	Tcl_AppendToObj(objPtr, "wrong # args: should be \"", TCL_INDEX_NONE);
    }

    /*
     * If processing an an ensemble implementation, rewrite the results in
     * terms of how the ensemble was invoked.
     */

    if (iPtr->ensembleRewrite.sourceObjs != NULL) {
	Tcl_Size toSkip = iPtr->ensembleRewrite.numInsertedObjs;
	Tcl_Size toPrint = iPtr->ensembleRewrite.numRemovedObjs;
	Tcl_Obj *const *origObjv = TclEnsembleGetRewriteValues(interp);

	/*








	 * 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 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;

	/*
	 * Assume no object is of index type.
	 */

	for (i=0 ; i<toPrint ; i++) {
	    /*
	     * Add the element, quoting it if necessary.
	     */
	    const Tcl_ObjInternalRep *irPtr;

	    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
	    }

	    /*
	     * 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);
	    }
	}
    }

    /*
     * 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
	 * the correct error message even if the subcommand was abbreviated.
	 * Otherwise, just use the string rep.
	 */
	const Tcl_ObjIntRep *irPtr;

	if ((irPtr = TclFetchIntRep(objv[i], &indexType))) {
	    IndexRep *indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;

	    Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), NULL);
	} else {
	    /*
	     * Quote the argument if it contains spaces (Bug 942757).
	     */

	    elementStr = TclGetStringFromObj(objv[i], &elemLen);
	    flags = 0;







|
|












|



|

|


|







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 + 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
	 * the correct error message even if the subcommand was abbreviated.
	 * Otherwise, just use the string rep.
	 */
	const Tcl_ObjInternalRep *irPtr;

	if ((irPtr = TclFetchInternalRep(objv[i], &tclIndexType))) {
	    IndexRep *indexRep = (IndexRep *)irPtr->twoPtrValue.ptr1;

	    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
	}

	/*
	 * 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);
	}
    }

    /*
     * 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, "\"", NULL);
    Tcl_SetErrorCode(interp, "TCL", "WRONGARGS", NULL);
    Tcl_SetObjResult(interp, objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ParseArgsObjv --







|
|










|

|
|







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 + 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, (char *)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
 *	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.
 *
 *----------------------------------------------------------------------
 */


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
				 * 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.*/
    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
				 * from objv. */
    int 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 */


    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]







>





|









|











|

|


|
|
>







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. */
    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. */
    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
				 * '-'). */
    Tcl_Size srcIndex;	/* Location from which to read next argument
				 * from objv. */
    Tcl_Size dstIndex;	/* Used to keep track of current arguments
				 * being processed, primarily for error
				 * reporting. */
    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
	if (length > 0) {
	    c = str[1];
	} else {
	    c = 0;
	}

	/*
	 * Loop throught 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) {







|







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 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
	    if (handlerProc(infoPtr->clientData, argObj, infoPtr->dstPtr)) {
		srcIndex++;
		objc--;
	    }
	    break;
	}
	case TCL_ARGV_GENFUNC: {






	    Tcl_ArgvGenFuncProc *handlerProc = (Tcl_ArgvGenFuncProc *)
		    infoPtr->srcPtr;

	    objc = handlerProc(infoPtr->clientData, interp, objc,
		    &objv[srcIndex], infoPtr->dstPtr);
	    if (objc < 0) {
		goto error;



	    }
	    break;
	}
	case TCL_ARGV_HELP:
	    PrintUsage(interp, argTable);
	    goto error;
	default:







>
>
>
>
>
>



|

|

>
>
>







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;

	    gf_ret = handlerProc(infoPtr->clientData, interp, objc,
		    &objv[srcIndex], infoPtr->dstPtr);
	    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
				/* 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;

	if (infoPtr->keyStr == NULL) {
	    continue;
	}
	length = strlen(infoPtr->keyStr);
	if (length > (size_t)width) {
	    width = length;
	}
    }

    /*
     * Now add the option information, with pretty-printing.
     */

    msg = Tcl_NewStringObj("Command-specific options:", -1);
    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);
	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);







<









|





|








|















|








<







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[] = "                    ";

    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++) {
	Tcl_Size length;

	if (infoPtr->keyStr == NULL) {
	    continue;
	}
	length = strlen(infoPtr->keyStr);
	if (length > width) {
	    width = length;
	}
    }

    /*
     * Now add the option information, with pretty-printing.
     */

    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, 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));

	    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
    Tcl_Obj *value,
    int *codePtr)		/* Argument objects. */
{
    static const char *const returnCodes[] = {
	"ok", "error", "return", "break", "continue", NULL
    };

    if (!TclHasIntRep(value, &indexType)
	    && TclGetIntFromObj(NULL, value, codePtr) == TCL_OK) {
	return TCL_OK;
    }
    if (Tcl_GetIndexFromObj(NULL, value, returnCodes, 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);
    }
    return TCL_ERROR;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|



|
|












|











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 (!TclHasInternalRep(value, &tclIndexType)
	    && TclGetIntFromObj(NULL, value, codePtr) == TCL_OK) {
	return 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", (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
# 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 <[email protected]>
#
# 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


# 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,
	    Tcl_Channel errorChan)
}
declare 6 {
    void TclCleanupCommand(Command *cmdPtr)
}
declare 7 {
    size_t TclCopyAndCollapse(size_t 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_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)
}
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)
}
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 {
#    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 {
#    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)
#}
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)
}
declare 40 {
    int TclGetOpenMode(Tcl_Interp *interp, const char *str, int *seekFlagPtr)
}
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 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:
#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 54 {
    int TclInvokeStringCommand(void *clientData, Tcl_Interp *interp,
	    int 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)
}

declare 63 {
    int TclObjInterpProc(void *clientData, Tcl_Interp *interp,
	    int objc, Tcl_Obj *const objv[])
}

declare 64 {
    int TclObjInvoke(Tcl_Interp *interp, int 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)
}
#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)
}
declare 76 {
    Tcl_WideUInt 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)
}
#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)
}
declare 97 {
    void TclResetShadowedCmdRefs(Tcl_Interp *interp, Command *newCmdPtr)
}
declare 98 {
    int TclServiceIdle(void)
}
# Removed in 8.4b2:
#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,
#	    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)
}
# 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,
#	    Tcl_Obj *objPtr)
#}
# Removed in 9.0:
#declare 113 {
#    Tcl_Namespace *Tcl_CreateNamespace(Tcl_Interp *interp, const char *name,
#	    void *clientData, Tcl_NamespaceDeleteProc *deleteProc)
#}
# Removed in 9.0:
#declare 114 {
#    void Tcl_DeleteNamespace(Tcl_Namespace *nsPtr)
#}
# Removed in 9.0:
#declare 115 {
#    int Tcl_Export(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_Namespace *contextNsPtr, int flags)
#}
# Removed in 9.0:
#declare 117 {
#    Tcl_Namespace *Tcl_FindNamespace(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)







|
|
|









>






<
<
<
<
<
<
<
<
<
<



<
<
<
<

|






|

<
<
<
<
<
<

<

|














<
<
<
<
<



<
<
<
<



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|
|






|




<
<
<
<
<
<
<
<
<



<
<
<
<
<
<
<
<
<







|
|
<
<
<
<



<
|
<
<
<
<
<
|

<
<
<







|


|







<
|
|
>
|
<
|
|
<
>






<
<
<
<
<
<
<
<
<
<
<
<
<
<








|
<
<
<
<
|
|
|
<
>
|
|
|
<
>



<
<
<
<
<
<
<
<
<
<





<
<
<
<
<









>
|
|
|
<
>

|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|

<
<
<
<
<
<
<
<
<
<
<
<
<




|


|

<




<
<
<
<
<
<
<
<
<
<
<
<
<

|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









<
<
<
<











<
<
<
<
<
<
<
<
<










|
<
<
<
<
<
|
|
<

<
<
<











<
<
<
<
<
<
<
<
<
<







|

<
<
<
<











|


<

|


<

|

<

|


<

|


<

|














<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




<
<
<
<
<















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



<
<
<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26










27
28
29




30
31
32
33
34
35
36
37
38
39






40

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56





57
58
59




60
61
62
















63
64
65
66
67
68
69
70
71
72
73
74
75
76
77









78
79
80









81
82
83
84
85
86
87
88
89




90
91
92

93





94
95



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

114
115
116
117

118
119

120
121
122
123
124
125
126














127
128
129
130
131
132
133
134
135




136
137
138

139
140
141
142

143
144
145
146










147
148
149
150
151





152
153
154
155
156
157
158
159
160
161
162
163
164

165
166
167
168
169















170
171
172













173
174
175
176
177
178
179
180
181

182
183
184
185













186
187
188























189
190
191
192
193
194
195
196
197




198
199
200
201
202
203
204
205
206
207
208









209
210
211
212
213
214
215
216
217
218
219





220
221

222



223
224
225
226
227
228
229
230
231
232
233










234
235
236
237
238
239
240
241
242




243
244
245
246
247
248
249
250
251
252
253
254
255
256

257
258
259
260

261
262
263

264
265
266
267

268
269
270
271

272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287






















288
289
290
291





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 © 1998-1999 Scriptics Corporation.
# Copyright © 2001 Kevin B. Kenny.  All rights reserved.
# Copyright © 2007 Daniel A. Steffen <[email protected]>
#
# 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.











declare 3 {
    void TclAllocateFreeObjects(void)
}




declare 5 {
    int TclCleanupChildren(Tcl_Interp *interp, Tcl_Size numPids, Tcl_Pid *pidPtr,
	    Tcl_Channel errorChan)
}
declare 6 {
    void TclCleanupCommand(Command *cmdPtr)
}
declare 7 {
    Tcl_Size TclCopyAndCollapse(Tcl_Size count, const char *src, char *dst)
}






# TclCreatePipeline unofficially exported for use by BLT.

declare 9 {
    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)
}





declare 14 {
    int TclDumpMemoryInfo(void *clientData, int flags)
}




declare 16 {
    void TclExprFloatError(Tcl_Interp *interp, double value)
}
















declare 22 {
    int TclFindElement(Tcl_Interp *interp, const char *listStr,
	    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 {
    Tcl_Size TclFormatInt(char *buffer, Tcl_WideInt n)
}
declare 25 {
    void TclFreePackageInfo(Interp *iPtr)
}









declare 28 {
    Tcl_Channel TclpGetDefaultStdChannel(int type)
}









declare 31 {
    const char *TclGetExtension(const char *name)
}
declare 32 {
    int TclGetFrame(Tcl_Interp *interp, const char *str,
	    CallFrame **framePtrPtr)
}
# Removed in 9.0:
#declare 34 {




#    int TclGetIntForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
#	    int endValue, int *indexPtr)
#}

#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 {
    Tcl_ObjCmdProc *TclGetObjInterpProc(void)
}
declare 40 {
    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)
}

declare 43 {
    Tcl_ObjCmdProc2 *TclGetObjInterpProc2(void)
}
# Removed in 9.0:

#declare 44 {
#    int TclGuessPackageName(const char *fileName, Tcl_DString *bufPtr)

#}
declare 45 {
    int TclHideUnsafeCommands(Tcl_Interp *interp)
}
declare 46 {
    int TclInExit(void)
}














# Removed in 9.0:
#declare 50 {
#    void TclInitCompiledLocals(Tcl_Interp *interp, CallFrame *framePtr,
#	    Namespace *nsPtr)
#}
declare 51 {
    int TclInterpInit(Tcl_Interp *interp)
}
# Removed in 9.0




#declare 53 {
#    int TclInvokeObjectCommand(void *clientData, Tcl_Interp *interp,
#	    Tcl_Size argc, const char **argv)

#}
#declare 54 {
#    int TclInvokeStringCommand(void *clientData, Tcl_Interp *interp,
#	    Tcl_Size objc, Tcl_Obj *const objv[])

#}
declare 55 {
    Proc *TclIsProc(Command *cmdPtr)
}










declare 58 {
    Var *TclLookupVar(Tcl_Interp *interp, const char *part1, const char *part2,
	    int flags, const char *msg, int createPart1, int createPart2,
	    Var **arrayPtrPtr)
}





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,
#	    Tcl_Size objc, Tcl_Obj *const objv[])

#}
declare 64 {
    int TclObjInvoke(Tcl_Interp *interp, Tcl_Size objc, Tcl_Obj *const objv[],
	    int flags)
}















declare 69 {
    void *TclpAlloc(TCL_HASH_TYPE size)
}













declare 74 {
    void TclpFree(void *ptr)
}
declare 75 {
    unsigned long long TclpGetClicks(void)
}
declare 76 {
    unsigned long long TclpGetSeconds(void)
}

# Removed in 9.0:
#declare 77 {
#    void TclpGetTime(Tcl_Time *time)
#}













declare 81 {
    void *TclpRealloc(void *ptr, TCL_HASH_TYPE size)
}























# 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)
}




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)
}









declare 96 {
    int TclRenameCommand(Tcl_Interp *interp, const char *oldName,
            const char *newName)
}
declare 97 {
    void TclResetShadowedCmdRefs(Tcl_Interp *interp, Command *newCmdPtr)
}
declare 98 {
    int TclServiceIdle(void)
}
# Removed in 9.0:





#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)
#}










declare 108 {
    void TclTeardownNamespace(Namespace *nsPtr)
}
declare 109 {
    int TclUpdateReturnInfo(Interp *iPtr)
}
declare 110 {
    int TclSockMinimumBuffers(void *sock, Tcl_Size size)
}





# 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 TclAppendExportList(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
#	    Tcl_Obj *objPtr)
#}

#declare 113 {
#    Tcl_Namespace *TclCreateNamespace(Tcl_Interp *interp, const char *name,
#	    void *clientData, Tcl_NamespaceDeleteProc *deleteProc)
#}

#declare 114 {
#    void TclDeleteNamespace(Tcl_Namespace *nsPtr)
#}

#declare 115 {
#    int TclExport(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
#	    const char *pattern, int resetListFirst)
#}

#declare 116 {
#    Tcl_Command TclFindCommand(Tcl_Interp *interp, const char *name,
#	    Tcl_Namespace *contextNsPtr, int flags)
#}

#declare 117 {
#    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)
}






















declare 126 {
    void Tcl_GetVariableFullName(Tcl_Interp *interp, Tcl_Var variable,
	    Tcl_Obj *objPtr)
}





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 138 {
    const char *TclGetEnv(const char *name, Tcl_DString *valuePtr)
}








# 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
}
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)
}
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)
}







<
<
<




|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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)
}



declare 150 {
    int TclRegAbout(Tcl_Interp *interp, Tcl_RegExp re)
}
declare 151 {
    void TclRegExpRangeUniChar(Tcl_RegExp re, Tcl_Size index, Tcl_Size *startPtr,
	    Tcl_Size *endPtr)
}

















declare 156 {
    void TclRegError(Tcl_Interp *interp, const char *msg,
	    int status)
}
declare 157 {
    Var *TclVarTraceExists(Tcl_Interp *interp, const char *varName)
}















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
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)
}

# 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
declare 169 {
    int TclpUtfNcmp2(const char *s1, const char *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[])
}
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[])
}
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)
}

# 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,







|


<
<
<
<
<
<
<
<
<
|

|



|
|



|
|




<
<
<

|
|

<
<
<
<
<
<
<
<
<
<











<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




<
<
<
<
<







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,
	    Tcl_Size index, Tcl_Obj *valuePtr)
}










# variant of Tcl_UtfNcmp that takes n as bytes, not chars
declare 169 {
    int TclpUtfNcmp2(const void *s1, const void *s2, size_t n)
}
declare 170 {
    int TclCheckInterpTraces(Tcl_Interp *interp, const char *command,
	    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,
	    Tcl_Size numChars, Command *cmdPtr, int result, int traceFlags,
	    Tcl_Size objc, Tcl_Obj *const objv[])
}
declare 172 {
    int TclInThreadExit(void)
}



declare 173 {
    int TclUniCharMatch(const Tcl_UniChar *string, Tcl_Size strLen,
	    const Tcl_UniChar *pattern, Tcl_Size ptnLen, int flags)
}










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)
}
















































































declare 198 {
    int TclObjGetFrame(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    CallFrame **framePtrPtr)
}





# 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
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)
}
declare 216 {
    void TclStackFree(Tcl_Interp *interp, void *freePtr)
}
declare 217 {
    int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr,
            Tcl_Namespace *namespacePtr, int isProcCallFrame)
}
declare 218 {
    void TclPopStackFrame(Tcl_Interp *interp)
}






# for use in tclTest.c













declare 224 {
    TclPlatformType *TclGetPlatform(void)
}

#
declare 225 {
    Tcl_Obj *TclTraceDictPath(Tcl_Interp *interp, Tcl_Obj *rootPtr,
	    int 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[])
}
#  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)
}
declare 231 {
    int	TclGetNamespaceFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
	    Tcl_Namespace **nsPtrPtr)
}

# Bits and pieces of TIP#280's guts







<
<
<
<
<
<
<
<
<
<










|











>
>
>
>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>



<
<


|





|


<
<
<
<
<
<







|







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
declare 207 {
    int TclpObjAccess(Tcl_Obj *pathPtr, int mode)
}
declare 208 {
    Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp,
	    Tcl_Obj *pathPtr, int mode, int permissions)
}










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, 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)
}
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,
	    Tcl_Size keyc, Tcl_Obj *const keyv[], int flags)
}
declare 226 {
    int TclObjBeingDeleted(Tcl_Obj *objPtr)
}
declare 227 {
    void TclSetNsPath(Namespace *nsPtr, Tcl_Size pathLength,
            Tcl_Namespace *pathAry[])
}






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,
	    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
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
    Var *TclVarHashCreateVar(TclVarHashTable *tablePtr, const char *key,
             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[])
}
declare 239 {
    int TclNRInterpProcCore(Tcl_Interp *interp, Tcl_Obj *procNameObj,
			    int 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,
	      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)
}
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)
}

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)
}

# 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)
}
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)
}
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)
}
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)
}
declare 257 {
    void TclStaticPackage(Tcl_Interp *interp, const char *pkgName,
	    Tcl_PackageInitProc *initProc, Tcl_PackageInitProc *safeInitProc)
}

# TIP 431: temporary directory creation function
declare 258 {
    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)
}

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

declare 0 win {
    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,
#	    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)
}
# 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 {
    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)
#}

# Pipe channel functions

declare 11 win {
    void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan)
}
declare 12 win {
    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,
	    const Tcl_StatBuf *statBufPtr, int dontCopyAtts)
}
declare 18 win {
    TclFile TclpMakeFile(Tcl_Channel channel, int direction)
}
declare 19 win {
    TclFile TclpOpenFile(const char *fname, int mode)
}
declare 20 win {
    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)
#}

# Added in 8.1:
declare 22 win {
    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 {
    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 {
    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,
	    const char **argv, TclFile inputFile, TclFile outputFile,
	    TclFile errorFile, Tcl_Pid *pidPtr)
}
declare 5 unix {
    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)
}

# Added in 8.1:

declare 9 unix {
    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} {
    int TclMacOSXGetFileAttribute(Tcl_Interp *interp, int objIndex,
	    Tcl_Obj *fileName, Tcl_Obj **attributePtrPtr)
}
declare 16 {unix macosx} {
    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,
	    Tcl_GlobTypeData *types)
}
declare 19 {unix macosx} {
    void TclMacOSXNotifierAddRunLoopMode(const void *runLoopMode)
}
declare 22 {unix macosx} {
    TclFile TclpCreateTempFile_(const char *contents)
}

declare 29 {win unix} {
    int TclWinCPUID(int index, int *regs)
}
# Added in 8.6; core of TclpOpenTemporaryFile
declare 30 {win unix} {
    int TclUnixOpenTemporaryFile(Tcl_Obj *dirObj, Tcl_Obj *basenameObj,
	    Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj)
}

# Local Variables:
# mode: tcl
# End:







<
<
<
<
<
<









|



|










|
















|
|







|














|







|




|




|







|


|
|


<
|
<
<
<
<
<
<
<
<
|
<
<
<

<









|

|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<

<
|
>
|

<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
|
|

|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<

|


|


|
<
<
<
<
<
<
<
<
|
<
|
<
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|
<
<
<
<
<
<
<
<
<
<
|



|
<
<
<
<
<
<
<
<
<
<
<
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



<
<
<
<
|
<
|

|
<
<
<
<
<
<
<
<
<
|
<

|
|

<
<
<
<
|


<
|







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
    Var *TclVarHashCreateVar(TclVarHashTable *tablePtr, const char *key,
             int *newPtr)
}
declare 235 {
    void TclInitVarHashTable(TclVarHashTable *tablePtr, Namespace *nsPtr)
}







# 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,
	    Tcl_Size objc, Tcl_Obj *const objv[])
}
declare 239 {
    int TclNRInterpProcCore(Tcl_Interp *interp, Tcl_Obj *procNameObj,
	    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, 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, 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, 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, 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,
	    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, 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, 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, int flags)
}
declare 257 {
    void TclStaticLibrary(Tcl_Interp *interp, const char *prefix,
	    Tcl_LibraryInitProc *initProc, Tcl_LibraryInitProc *safeInitProc)
}


declare 261 {








    void TclUnusedStubEntry(void)



}


##############################################################################

# Define the platform specific internal Tcl interface. These functions are
# only available on the designated platform.

interface tclIntPlat

################################
# Platform specific functions

declare 1 {













    int TclpCloseFile(TclFile file)




}

declare 2 {
    Tcl_Channel TclpCreateCommandChannel(TclFile readFile,
	    TclFile writeFile, TclFile errorFile, size_t numPids, Tcl_Pid *pidPtr)
}













declare 3 {














    int TclpCreatePipe(TclFile *readPipe, TclFile *writePipe)

}
declare 4 {
    void *TclWinGetTclInstance(void)
}
declare 5 {



























    int TclUnixWaitForFile(int fd, int mask, int timeout)

}
declare 6 {
    TclFile TclpMakeFile(Tcl_Channel channel, int direction)
}
declare 7 {
    TclFile TclpOpenFile(const char *fname, int mode)
}
declare 8 {








    Tcl_Size TclpGetPid(Tcl_Pid pid)

}

declare 9 {
    TclFile TclpCreateTempFile(const char *contents)
}


















declare 11 {
















    void TclGetAndDetachPids(Tcl_Interp *interp, Tcl_Channel chan)
}
declare 15 {










    int TclpCreateProcess(Tcl_Interp *interp, size_t argc,
	    const char **argv, TclFile inputFile, TclFile outputFile,
	    TclFile errorFile, Tcl_Pid *pidPtr)
}
declare 16 {











    int TclpIsAtty(int fd)

}
declare 17 {

























    int TclUnixCopyFile(const char *src, const char *dst,
	    const Tcl_StatBuf *statBufPtr, int dontCopyAtts)
}




declare 20 {

    void TclWinAddProcess(void *hProcess, Tcl_Size id)
}
declare 24 {









    char *TclWinNoBackslash(char *path)

}
declare 27 {
    void TclWinFlushDirtyChannels(void)
}




declare 29 {
    int TclWinCPUID(int index, int *regs)
}

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

#include "tclPort.h"

#include <stdio.h>

#include <ctype.h>
#include <stdarg.h>
#ifdef NO_STDLIB_H
#   include "../compat/stdlib.h"
#else
#   include <stdlib.h>
#endif
#ifdef NO_STRING_H
#include "../compat/string.h"
#else
#include <string.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 <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).
 */







<
<
<
|
|





<
<
<
<
<







62
63
64
65
66
67
68



69
70
71
72
73
74
75





76
77
78
79
80
81
82

#include "tclPort.h"

#include <stdio.h>

#include <ctype.h>
#include <stdarg.h>



#include <stdlib.h>
#include <stdint.h>
#ifdef NO_STRING_H
#include "../compat/string.h"
#else
#include <string.h>
#endif





#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

/*
 * 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(HAVE_INTPTR_T) || defined(intptr_t)
#	define INT2PTR(p) ((void *)(intptr_t)(p))
#	define PTR2INT(p) ((intptr_t)(p))
#   else
#	define INT2PTR(p) ((void *)(p))
#	define PTR2INT(p) ((long)(p))
#   endif
#endif
#if !defined(UINT2PTR) && !defined(PTR2UINT)
#   if defined(HAVE_UINTPTR_T) || defined(uintptr_t)
#	define UINT2PTR(p) ((void *)(uintptr_t)(p))
#	define PTR2UINT(p) ((uintptr_t)(p))
#   else
#	define UINT2PTR(p) ((void *)(p))
#	define PTR2UINT(p) ((unsigned long)(p))
#   endif
#endif

#if defined(_WIN32) && defined(_MSC_VER)
#   define vsnprintf _vsnprintf

#endif

#if !defined(TCL_THREADS)
#   define TCL_THREADS 1
#endif
#if !TCL_THREADS
#   undef TCL_DECLARE_MUTEX







|
<
|
<
|
|
|
<

|
<
|
<
|
|
|
<




>







103
104
105
106
107
108
109
110

111

112
113
114

115
116

117

118
119
120

121
122
123
124
125
126
127
128
129
130
131
132

/*
 * 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)

#   define INT2PTR(p) ((void *)(ptrdiff_t)(p))

#endif
#if !defined(PTR2INT)
#   define PTR2INT(p) ((ptrdiff_t)(p))

#endif
#if !defined(UINT2PTR)

#   define UINT2PTR(p) ((void *)(size_t)(p))

#endif
#if !defined(PTR2UINT)
#   define PTR2UINT(p) ((size_t)(p))

#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

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,
	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);







|







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

typedef struct Tcl_ResolvedVarInfo {
    Tcl_ResolveRuntimeVarProc *fetchProc;
    Tcl_ResolveVarDeleteProc *deleteProc;
} Tcl_ResolvedVarInfo;

typedef int (Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp,
	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
 *----------------------------------------------------------------
 */

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.
 */

typedef struct TclVarHashTable {
    Tcl_HashTable table;
    struct Namespace *nsPtr;



} TclVarHashTable;

/*
 * This is for itcl - it likes to search our varTables directly :(
 */

#define TclVarHashFindVar(tablePtr, key) \







|
|
|
|





>
>
>







209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
 *----------------------------------------------------------------
 */

typedef struct Tcl_Ensemble Tcl_Ensemble;
typedef struct NamespacePathEntry NamespacePathEntry;

/*
 * 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;
#if TCL_MAJOR_VERSION > 8
    struct Var *arrayPtr;
#endif /* TCL_MAJOR_VERSION > 8 */
} TclVarHashTable;

/*
 * This is for itcl - it likes to search our varTables directly :(
 */

#define TclVarHashFindVar(tablePtr, key) \
280
281
282
283
284
285
286

287



288
289
290
291
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
				 * 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

    size_t nsId;		/* Unique id for the namespace. */



    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
				 * 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
				 * 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
				 * registered using "namespace export". */
    size_t maxExportPatterns;	/* Number of export patterns for which space
				 * is currently allocated. */
    size_t 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
				 * 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;







>

>
>
>




|



|




















|

|

|




|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
				 * 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
				 * namespace. */
    int flags;			/* OR-ed combination of the namespace status
				 * flags NS_DYING and NS_DEAD listed below. */
    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. */
    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. */
    Tcl_Size numExportPatterns;	/* Number of export patterns currently
				 * registered using "namespace export". */
    Tcl_Size maxExportPatterns;	/* Number of export patterns for which space
				 * is currently allocated. */
    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. */
    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
    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
				 * 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. */
    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;







|










|







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
    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. */
    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. */
    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
				 * 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
 *		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.
 * 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 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.
 * 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_KILLED	0x04
#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.


 */

#define TCL_CREATE_NS_IF_UNKNOWN	0x800
#define TCL_FIND_ONLY_NS		0x1000


/*
 * 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
				 * 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,







|

|
|
>
|

|
|
<
|
|
|
|
<
<







>
|









>
>




>
















|







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
				 * commandPathSourceList field. */
};

/*
 * Flags used to represent the status of a namespace:
 *
 * NS_DYING -	1 means Tcl_DeleteNamespace has been called to delete the
 *		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, 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. It is no longer
 *		accessible by name. Its variables and commands have already

 *		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_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 /* 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.) */
    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
    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,
				 * 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







|







469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
    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;			/* 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
				 * 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
				 * 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
				 * 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.







|



|







496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
				 * 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 re-parsed by the ensemble
				 * core, presumably because the ensemble
				 * itself has been updated. */
    Tcl_Obj *parameterList;	/* List of ensemble parameter names. */
    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.
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
    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
				 * 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)







|







556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
    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. */
    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)
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
				 * "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
				 * 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
				 * 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
 *				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.





 *
 * 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
 *				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
 *				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







|










|










|








>
>
>
>
>




|
|



|







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
				 * "upvar", this field points to the
				 * referenced variable's Var struct. */
    } value;
} Var;

typedef struct VarInHash {
    Var 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
				 * 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 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 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 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
 * 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


/* 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 */








>







729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
 * 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
/*
 * 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	TclSetVarArrayElement(Var *varPtr);
 * MODULE_SCOPE void	TclSetVarUndefined(Var *varPtr);
 * MODULE_SCOPE void	TclClearVarUndefined(Var *varPtr);
 */

#define TclSetVarScalar(varPtr) \
    (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK)

#define TclSetVarArray(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~VAR_LINK) | VAR_ARRAY

#define TclSetVarLink(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_LINK




#define TclSetVarArrayElement(varPtr) \
    (varPtr)->flags = ((varPtr)->flags & ~VAR_ARRAY) | VAR_ARRAY_ELEMENT

#define TclSetVarUndefined(varPtr) \
    (varPtr)->flags &= ~(VAR_ARRAY|VAR_LINK);\
    (varPtr)->value.objPtr = NULL

#define TclClearVarUndefined(varPtr)

#define TclSetVarTraceActive(varPtr) \
    (varPtr)->flags |= VAR_TRACE_ACTIVE








>






|







>
>
>




|







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
/*
 * 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|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|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
    }

/*
 * 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	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 TclIsVarScalar(varPtr) \
    !((varPtr)->flags & (VAR_ARRAY|VAR_LINK))

#define TclIsVarLink(varPtr) \
    ((varPtr)->flags & VAR_LINK)

#define TclIsVarArray(varPtr) \
    ((varPtr)->flags & VAR_ARRAY)





#define TclIsVarUndefined(varPtr) \
    ((varPtr)->value.objPtr == NULL)

#define TclIsVarArrayElement(varPtr) \
    ((varPtr)->flags & VAR_ARRAY_ELEMENT)

#define TclIsVarNamespaceVar(varPtr) \







>








>
>
>
>
>
>
>
>










>
>
>
>







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
    }

/*
 * 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
    ((varPtr)->flags & VAR_DEAD_HASH)

#define TclGetVarNsPtr(varPtr) \
    (TclIsVarInHash(varPtr) \
	? ((TclVarHashTable *) ((((VarInHash *) (varPtr))->entry.tablePtr)))->nsPtr \
	: NULL)




#define VarHashRefCount(varPtr) \
    ((VarInHash *) (varPtr))->refCount




/*
 * Macros for direct variable access by TEBC.
 */







#define TclIsVarDirectReadable(varPtr) \
    (   !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ)) \
    &&  (varPtr)->value.objPtr)

#define TclIsVarDirectWritable(varPtr) \
    !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_WRITE|VAR_DEAD_HASH))

#define TclIsVarDirectUnsettable(varPtr) \
    !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_TRACED_UNSET|VAR_DEAD_HASH))

#define TclIsVarDirectModifyable(varPtr) \
    (   !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ|VAR_TRACED_WRITE)) \
    &&  (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(__GNUC__) && (__GNUC__ > 2)
#   define TCLFLEXARRAY 0
#else
#   define TCLFLEXARRAY 1
#endif

/*
 * Forward declaration to prevent an error when the forward reference to







>
>
>



>
>
>




>
>
>
>
>
>
|
|
|


|


|


|
|




















>
>
|







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
    ((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)					\
    (   (!TclIsVarTricky(varPtr,VAR_TRACED_READ))			\
          && (varPtr)->value.objPtr)

#define TclIsVarDirectWritable(varPtr) \
    (!TclIsVarTricky(varPtr,VAR_TRACED_WRITE|VAR_DEAD_HASH|VAR_CONSTANT))

#define TclIsVarDirectUnsettable(varPtr) \
    (!TclIsVarTricky(varPtr,VAR_TRACED_READ|VAR_TRACED_WRITE|VAR_TRACED_UNSET|VAR_DEAD_HASH|VAR_CONSTANT))

#define TclIsVarDirectModifyable(varPtr) \
    (   (!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
#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
 */

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.
				 * Among others used to speed up var lookups. */
    int frameIndex;		/* Index in the array of compiler-assigned
				 * variables in the procedure call frame. */

    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. */
    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. */






    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
				 * 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
				 * 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







|

|

>
|
<
<
|










>
>
>
>
>
>
















|










|
|







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
 */

typedef struct CompiledLocal {
    struct CompiledLocal *nextPtr;
				/* Next compiler-recognized local variable for
				 * this procedure, or NULL if this is the last
				 * local. */
    Tcl_Size nameLength;		/* The number of bytes in local variable's name.
				 * Among others used to speed up var lookups. */
    Tcl_Size frameIndex;		/* Index in the array of compiler-assigned
				 * variables in the procedure call frame. */
#if TCL_MAJOR_VERSION < 9
    int flags;


#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
				 * 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. */
    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. */
    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

/*
 * 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
				 * than or equal to this. */



    Tcl_CmdObjTraceProc *proc;	/* Procedure to call to trace command. */

    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;







|

>
>
>

>







1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067

/*
 * 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 {
    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. */
    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;
1054
1055
1056
1057
1058
1059
1060
































































































1061
1062
1063
1064
1065
1066
1067
 * TCL_TRACE_LEAVE_EXEC		- triggers leave/leavestep traces.
 * 				- passed to Tcl_CreateObjTrace to set up
 *				  "leavestep" traces.
 */

#define TCL_TRACE_ENTER_EXEC	1
#define TCL_TRACE_LEAVE_EXEC	2

































































































/*
 * 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.
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 * TCL_TRACE_LEAVE_EXEC		- triggers leave/leavestep traces.
 * 				- 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, struct Tcl_Obj *valueObj,
		     struct 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.
 */
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

/*
 * 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;
} 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
				 * for this procedure call. */
    Tcl_Obj *const *objv;	/* Array of argument objects. */
    struct CallFrame *callerPtr;
				/* 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"
				 * 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. */
    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
				 * object systems. The meaning of the contents
				 * of this field is defined by the code that







|
|



















|













|













|
|







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

/*
 * 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 {
    Tcl_Size refCount;
    Tcl_Size numVars;
    Tcl_Obj *varName0;
} 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. */
    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;
				/* 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). */
    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. */
    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
				 * object systems. The meaning of the contents
				 * of this field is defined by the code that
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
    /*
     * 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;
    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







|
|







1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
    /*
     * General data. Always available.
     */

    int type;			/* Values see below. */
    int level;			/* Number of frames in stack, prevent O(n)
				 * scan of list. */
    Tcl_Size *line;		/* Lines the words of the command start on. */
    Tcl_Size nline;
    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
	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. */
    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
				 * stack. */
} CFWord;

typedef struct CFWordBC {
    CmdFrame *framePtr;		/* CmdFrame to access. */
    size_t pc;			/* Instruction pointer of a command in
				 * ExtCmdLoc.loc[.] */
    int 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 */
} 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 "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
				 * final -1 marker entry. */
    int 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;








|









|
|





|

|




|













|









|

|







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
	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... */
    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. */
    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. */
    Tcl_Size pc;			/* Instruction pointer of a command in
				 * ExtCmdLoc.loc[.] */
    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 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 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 {
    Tcl_Size num;			/* Number of entries in loc, not counting the
				 * final -1 marker entry. */
    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;

1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
    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
				 * proc field is NULL. */
} ExtraFrameInfoField;
typedef struct {
    size_t length;			/* Length of array. */
    ExtraFrameInfoField fields[2];
				/* Really as long as necessary, but this is
				 * long enough for nearly anything. */
} ExtraFrameInfo;

/*
 *----------------------------------------------------------------







|







1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
    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
				 * proc field is NULL. */
} ExtraFrameInfoField;
typedef struct {
    Tcl_Size length;			/* Length of array. */
    ExtraFrameInfoField fields[2];
				/* Really as long as necessary, but this is
				 * long enough for nearly anything. */
} ExtraFrameInfo;

/*
 *----------------------------------------------------------------
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
 * 			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.
 */







<
<


<
<







1552
1553
1554
1555
1556
1557
1558


1559
1560


1561
1562
1563
1564
1565
1566
1567
 * 			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.


 */



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.
 */
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484





1485
1486
1487
1488
1489
1490
1491
				 * 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
				 * 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" */





} 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;







|



|
|
|
>
>
>
>
>







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
				 * the coroutine, which might be the
				 * interpreter global environment or another
				 * coroutine. */
    CorContext caller;
    CorContext running;
    Tcl_HashTable *lineLABCPtr;    /* See Interp.lineLABCPtr */
    void *stackLevel;
    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. */
    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;
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

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
				 * 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
				 * **buckets. */
    size_t numEntries;		/* Total number of entries present in
				 * table. */
    size_t rebuildSize;		/* Enlarge table when numEntries gets to be
				 * this large. */
    size_t 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.
 */







|

















|

|

|

|







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

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. */
    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. */
    TCL_HASH_TYPE numBuckets; /* Total number of buckets allocated at
				 * **buckets. */
    TCL_HASH_TYPE numEntries; /* Total number of entries present in
				 * table. */
    TCL_HASH_TYPE rebuildSize; /* Enlarge table when numEntries gets to be
				 * this large. */
    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.
 */
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
				 * 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
				 * 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
				 * 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. */







|




|







1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
				 * 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. */
    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. */
    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. */
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
    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
				 * track of parent/child interps on a
				 * per-interp basis. */

    void (*optimizer)(void *envPtr);










    /*
     * 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_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
				 * 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. */







    /*
     * 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
				 * 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. */



    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
				 * 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







>

>
>
>
>
>
>
>
>
>
>





|




|

















>
>
>
>
>
>
















|





>
>
>





|







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
    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
				 * track of parent/child interps on a
				 * per-interp basis. */
#if TCL_MAJOR_VERSION > 8
    void (*optimizer)(void *envPtr);
#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.
     */

    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. */
    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:
     */

    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. */
    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
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
    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. */



    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
				 * tracePtr) that forbid inline bytecode
				 * compilation. */

    /*
     * Fields used to manage extensible return options (TIP 90).
     */








>
>
>












|







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
    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. */

    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
				 * 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
				 * 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. */








|







2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
				 * 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. */

	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

    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
				 * because of ensemble processing. */
	size_t numInsertedObjs;	/* How many of the current arguments were
				 * inserted by an ensemble. */
    } ensembleRewrite;

    /*
     * TIP #219: Global info for the I/O system.
     */








|

|







2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179

    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. */
	Tcl_Size numRemovedObjs;	/* How many arguments have been stripped off
				 * because of ensemble processing. */
	Tcl_Size numInsertedObjs;	/* How many of the current arguments were
				 * inserted by an ensemble. */
    } ensembleRewrite;

    /*
     * TIP #219: Global info for the I/O system.
     */

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
#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
 * 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.

 *
 * 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.
 *
 * 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.
 */











#define TCL_ALIGN(x) (((int)(x) + 7) & ~7)


/*
 * A common panic alert when memory allocation fails.
 */

#define TclOOM(ptr, size) \
	((size) && ((ptr)||(Tcl_Panic("unable to alloc %" TCL_Z_MODIFIER "u bytes", (size_t)(size)),1)))







|

|
|
|
>


|
|






>
>
>
>
>
>
>
>
>
>
|
>







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
#if defined(__APPLE__)
#define TCL_ALLOCALIGN	16
#else
#define TCL_ALLOCALIGN	(2*sizeof(void *))
#endif

/*
 * 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 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 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) \
	(((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("unable to alloc %" TCL_Z_MODIFIER "u bytes", (size_t)(size)),1)))
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
 */

#define	TCL_INVOKE_HIDDEN	(1<<0)
#define TCL_INVOKE_NO_UNKNOWN	(1<<1)
#define TCL_INVOKE_NO_TRACEBACK	(1<<2)

/*


 * 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
				 * 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;

#define LIST_MAX \

	(1 + (int)(((size_t)UINT_MAX - sizeof(List))/sizeof(Tcl_Obj *)))




#define LIST_SIZE(numElems) \



	(sizeof(List) + (((numElems) - 1) * sizeof(Tcl_Obj *)))

/*
 * Macro used to get the elements of a list object.








 */
















#define ListRepPtr(listPtr) \








    ((List *) (listPtr)->internalRep.twoPtrValue.ptr1)


#define ListObjGetElements(listPtr, objc, objv) \

    ((objv) = &(ListRepPtr(listPtr)->elements), \



     (objc) = ListRepPtr(listPtr)->elemCount)




#define ListObjLength(listPtr, len) \


    ((len) = ListRepPtr(listPtr)->elemCount)






#define ListObjIsCanonical(listPtr) \


    (((listPtr)->bytes == NULL) || ListRepPtr(listPtr)->canonicalFlag)


































#define TclListObjGetElements(interp, listPtr, objcPtr, objvPtr) \
    (((listPtr)->typePtr == &tclListType) \
	    ? ((ListObjGetElements((listPtr), *(objcPtr), *(objvPtr))), TCL_OK)\

	    : Tcl_ListObjGetElements((interp), (listPtr), (objcPtr), (objvPtr)))







#define TclListObjLength(interp, listPtr, lenPtr) \
    (((listPtr)->typePtr == &tclListType) \
	    ? ((ListObjLength((listPtr), *(lenPtr))), TCL_OK)\
	    : Tcl_ListObjLength((interp), (listPtr), (lenPtr)))

#define TclListObjIsCanonical(listPtr) \
    (((listPtr)->typePtr == &tclListType) ? ListObjIsCanonical((listPtr)) : 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.
 */


#define TclGetBooleanFromObj(interp, objPtr, boolPtr) \
    (((objPtr)->typePtr == &tclIntType \
	    || (objPtr)->typePtr == &tclBooleanType) \
	? (*(boolPtr) = ((objPtr)->internalRep.wideValue!=0), TCL_OK)	\
	: Tcl_GetBooleanFromObj((interp), (objPtr), (boolPtr)))









#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)))
#else
#define TclGetLongFromObj(interp, objPtr, longPtr) \
    (((objPtr)->typePtr == &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)))
#endif

#define TclGetIntFromObj(interp, objPtr, intPtr) \
    (((objPtr)->typePtr == &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)))
#define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \
    ((((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)))

/*
 * 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)					\
	? (*(wideIntPtr) =						\
		((objPtr)->internalRep.wideValue), TCL_OK) :		\
	Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))

/*
 * Flag values for TclTraceDictPath().
 *







>
>
|
>
|
>
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
|
>
>
>
|
<
>
|
|
|
<
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
|
|
>
|
>
>
>
>
|
>
>
>
|


|
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
|

>
|
>
|
>
>
>
|
>
>

>
|
>
>
|
>
>
>
>

>
|
>
>
|
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
|
>

>
>
>
>
>
|
|
|
|

|
|

















>
|
|
|
|
|
>
>
>
>
>
>
>
>



|




|







|





|
|
|











|







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
 */

#define	TCL_INVOKE_HIDDEN	(1<<0)
#define TCL_INVOKE_NO_UNKNOWN	(1<<1)
#define TCL_INVOKE_NO_TRACEBACK	(1<<2)

/*
 * ListStore --
 *
 * 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 */


/* Max number of elements that can be contained in a list */
#define LIST_MAX                                               \
    ((Tcl_Size)(((size_t)TCL_SIZE_MAX - offsetof(ListStore, slots)) \
		   / 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

/*
 * 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 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_)])

/* 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(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 ListObjStart(listObj_)                                      \
    (ListObjSpanPtr(listObj_) ? ListObjSpanPtr(listObj_)->spanStart \
			      : ListObjStorePtr(listObj_)->firstUsed)

/* Stores the element count and base address of this list's elements */
#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_, listObj_, lenPtr_)         \
    ((TclHasInternalRep((listObj_), &tclListType))                   \
	 ? ((ListObjLength((listObj_), *(lenPtr_))), TCL_OK) \
	 : Tcl_ListObjLength((interp_), (listObj_), (lenPtr_)))

#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, 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) \
    ((TclHasInternalRep((objPtr), &tclIntType))	\
	    ? ((*(longPtr) = (objPtr)->internalRep.wideValue), TCL_OK) \
	    : Tcl_GetLongFromObj((interp), (objPtr), (longPtr)))
#else
#define TclGetLongFromObj(interp, objPtr, longPtr) \
    ((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)))
#endif

#define TclGetIntFromObj(interp, objPtr, intPtr) \
    ((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)))
#define TclGetIntForIndexM(interp, objPtr, endValue, idxPtr) \
    (((TclHasInternalRep((objPtr), &tclIntType)) && ((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) \
    ((TclHasInternalRep((objPtr), &tclIntType))					\
	? (*(wideIntPtr) =						\
		((objPtr)->internalRep.wideValue), TCL_OK) :		\
	Tcl_GetWideIntFromObj((interp), (objPtr), (wideIntPtr)))

/*
 * Flag values for TclTraceDictPath().
 *
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
/*
 * 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,
	Tcl_Encoding *encodingPtr);







/*
 * 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
				 * global value. */
    size_t 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
				 * copy when a "get" request comes in before
				 * any "set" request has been received. */







<
<
<
<
<
<
<
<
<
<


















<
<
<
<
<
<
<
<
<






|

>
>
>
>
>
>










|

|







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
/*
 * Opaque handle used in pipeline routines to encapsulate platform-dependent
 * state.
 */

typedef struct TclFile_ *TclFile;











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 for process-global values.
 *----------------------------------------------------------------
 */

typedef void (TclInitProcessGlobalValueProc)(char **valuePtr, TCL_HASH_TYPE *lengthPtr,
	Tcl_Encoding *encodingPtr);

#ifdef _WIN32
#   define TCLFSENCODING tclUtf8Encoding /* On Windows, all Unicode (except surrogates) are valid */
#else
#   define TCLFSENCODING NULL /* On Non-Windows, use the system encoding for validation checks */
#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 {
    Tcl_Size epoch;			/* Epoch counter to detect changes in the
				 * global value. */
    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
				 * copy when a "get" request comes in before
				 * any "set" request has been received. */
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
#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 */


/*
 *----------------------------------------------------------------------
 * Type values TclGetNumberFromObj


 *----------------------------------------------------------------------
 */

#define TCL_NUMBER_INT		2

#define TCL_NUMBER_BIG		3




#define TCL_NUMBER_DOUBLE	4











#define TCL_NUMBER_NAN		5

























































/*
 *----------------------------------------------------------------
 * 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;




MODULE_SCOPE Tcl_Encoding tclIdentityEncoding;









/*
 * 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 tclIntType;

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;







>


<
>
>



|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|
>
>
>


>
>
>
>
>
>
>
>
















<



>







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
#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
 *----------------------------------------------------------------------
 */

#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;
    }
}
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;

/*
 * 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 tclByteCodeType;
MODULE_SCOPE const Tcl_ObjType tclDoubleType;
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;
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
 */

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 */
} 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,







|







3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
 */

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. */
    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,
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

/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl modules but not used by the outside world:
 *----------------------------------------------------------------
 */

MODULE_SCOPE void	TclAppendBytesToByteArray(Tcl_Obj *objPtr,
			    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,
			    int loc);
MODULE_SCOPE void	TclAdvanceLines(int *line, const char *start,
			    const char *end);




MODULE_SCOPE void	TclArgumentEnter(Tcl_Interp *interp,
			    Tcl_Obj *objv[], int objc, CmdFrame *cf);
MODULE_SCOPE void	TclArgumentRelease(Tcl_Interp *interp,
			    Tcl_Obj *objv[], int objc);
MODULE_SCOPE void	TclArgumentBCEnter(Tcl_Interp *interp,
			    Tcl_Obj *objv[], int objc,
			    void *codePtr, CmdFrame *cfPtr, int cmd, size_t 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 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);
MODULE_SCOPE double	TclCeil(const void *a);
MODULE_SCOPE void	TclChannelPreserve(Tcl_Channel chan);
MODULE_SCOPE void	TclChannelRelease(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 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 void	TclContinuationsEnterDerived(Tcl_Obj *objPtr,
			    int start, int *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,
			    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 int	TclFindDictElement(Tcl_Interp *interp,
			    const char *dict, int dictLength,
			    const char **elementPtr, const char **nextPtr,
			    size_t *sizePtr, int *literalPtr);

/* 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);
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 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);

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);







|
<
<
<
|

|

>
>
>
>






|




>
>
>


|
|



>









|
|

|



|









>
>

|

|
>


|
|









>
>








<

|
>







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

/*
 *----------------------------------------------------------------
 * Procedures shared among Tcl modules but not used by the outside world:
 *----------------------------------------------------------------
 */

#if TCL_MAJOR_VERSION > 8



MODULE_SCOPE void	TclAdvanceContinuations(Tcl_Size *line, Tcl_Size **next,
			    int loc);
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);
MODULE_SCOPE void	TclArgumentRelease(Tcl_Interp *interp,
			    Tcl_Obj *objv[], int objc);
MODULE_SCOPE void	TclArgumentBCEnter(Tcl_Interp *interp,
			    Tcl_Obj *objv[], int 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,
			    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 Tcl_NRPostProc TclClearRootEnsemble;
MODULE_SCOPE int	TclCompareTwoNumbers(Tcl_Obj *valuePtr,
			    Tcl_Obj *value2Ptr);
MODULE_SCOPE ContLineLoc *TclContinuationsEnter(Tcl_Obj *objPtr, Tcl_Size num,
			    Tcl_Size *loc);
MODULE_SCOPE void	TclContinuationsEnterDerived(Tcl_Obj *objPtr,
			    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 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, Tcl_Size dictLength,
			    const char **elementPtr, const char **nextPtr,
			    Tcl_Size *sizePtr, int *literalPtr);
MODULE_SCOPE Tcl_Obj *	TclDictObjSmartRef(Tcl_Interp *interp, Tcl_Obj *);
/* TIP #280 - Modified token based evaluation, with line information. */
MODULE_SCOPE int	TclEvalEx(Tcl_Interp *interp, const char *script,
			    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 *const *TclFetchEnsembleRoot(Tcl_Interp *interp,
			    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
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);
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,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE char *	TclGetStringStorage(Tcl_Obj *objPtr,
			    size_t *sizePtr);
MODULE_SCOPE int	TclGetLoadedPackagesEx(Tcl_Interp *interp,
				const char *targetName,
				const char *packageName);
MODULE_SCOPE int	TclGetWideBitsFromObj(Tcl_Interp *, Tcl_Obj *,
				Tcl_WideInt *);
MODULE_SCOPE int	TclGlob(Tcl_Interp *interp, char *pattern,
			    Tcl_Obj *unquotedPrefix, int globFlags,
			    Tcl_GlobTypeData *types);
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,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclInfoCoroutineCmd(void *dummy, Tcl_Interp *interp,
			    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,
			    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[],
			    int forceRelative);




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[]);

/* TIP #280 */
MODULE_SCOPE void	TclListLines(Tcl_Obj *listObj, int line, int n,
			    int *lines, Tcl_Obj *const *elems);
MODULE_SCOPE Tcl_Obj *	TclListObjCopy(Tcl_Interp *interp, Tcl_Obj *listPtr);



MODULE_SCOPE Tcl_Obj *	TclListObjRange(Tcl_Obj *listPtr, size_t fromIdx,
			    size_t 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_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,
			    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 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_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);
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);
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);
MODULE_SCOPE int	TclProcessReturn(Tcl_Interp *interp,
			    int code, int level, Tcl_Obj *returnOpts);

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 *	TclNewFSPathObj(Tcl_Obj *dirPtr, const char *addStrRep,
			    size_t len);







MODULE_SCOPE int	TclpDeleteFile(const void *path);

MODULE_SCOPE void	TclpFinalizeCondition(Tcl_Condition *condPtr);
MODULE_SCOPE void	TclpFinalizeMutex(Tcl_Mutex *mutexPtr);

MODULE_SCOPE void	TclpFinalizePipes(void);
MODULE_SCOPE void	TclpFinalizeSockets(void);





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);
MODULE_SCOPE void	TclpInitLibraryPath(char **valuePtr,
			    size_t *lengthPtr, Tcl_Encoding *encodingPtr);
MODULE_SCOPE void	TclpInitLock(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_PathType TclpGetNativePathType(Tcl_Obj *pathPtr,
			    int *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 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,
			    int *quantifiersFoundPtr);
MODULE_SCOPE size_t	TclScanElement(const char *string, size_t length,
			    char *flagPtr);
MODULE_SCOPE void	TclSetBgErrorHandler(Tcl_Interp *interp,
			    Tcl_Obj *cmdPrefix);
MODULE_SCOPE void	TclSetBignumIntRep(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);
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 *bad, Tcl_Obj *fix);
MODULE_SCOPE void *	TclStackRealloc(Tcl_Interp *interp, void *ptr,
			    size_t 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);
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,
			    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,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclSubstOptions(Tcl_Interp *interp, int 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_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);
MODULE_SCOPE const char*TclGetCommandTypeName(Tcl_Command command);



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	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 int	TclpLoadMemory(Tcl_Interp *interp, void *buffer,
			    int size, int 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 double	TclpWideClickInMicrosec(void);
#else
#   ifdef _WIN32
#	define TCL_WIDE_CLICKS 1
MODULE_SCOPE Tcl_WideInt TclpGetWideClicks(void);
MODULE_SCOPE double	TclpWideClickInMicrosec(void);
#	define		TclpWideClicksToNanoseconds(clicks) \
				((double)(clicks) * TclpWideClickInMicrosec() * 1000)
#   endif
#endif
MODULE_SCOPE Tcl_WideInt 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);
/* Tip 430 */
MODULE_SCOPE int    TclZipfs_Init(Tcl_Interp *interp);



/*
 * 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))

/*
 *----------------------------------------------------------------
 * Command procedures in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	Tcl_AfterObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_AppendObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ApplyObjCmd(void *clientData,
			    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,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_CatchObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_CdObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitChanCmd(Tcl_Interp *interp);
MODULE_SCOPE int	TclChanCreateObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclChanPostEventObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclChanPopObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclChanPushObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE void	TclClockInit(Tcl_Interp *interp);
MODULE_SCOPE int	TclClockOldscanObjCmd(
			    void *clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_CloseObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ConcatObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ContinueObjCmd(void *clientData,
			    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(
			    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_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

/* Assemble command function */
MODULE_SCOPE int	Tcl_AssembleObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclNRAssembleObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitEncodingCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_EofObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ErrorObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_EvalObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ExecObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ExitObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ExprObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FblockedObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FconfigureObjCmd(
			    void *clientData, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FcopyObjCmd(void *dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitFileCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_FileEventObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FlushObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ForObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ForeachObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_FormatObjCmd(void *dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_GetsObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_GlobalObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_GlobObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_IfObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_IncrObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitInfoCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_InterpObjCmd(void *clientData,
			    Tcl_Interp *interp, int argc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_JoinObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LappendObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LassignObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LindexObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LinsertObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LlengthObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ListObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LmapObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LoadObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LpopObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LrangeObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LremoveObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LrepeatObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LreplaceObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LreverseObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsearchObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsetObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_LsortObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitNamespaceCmd(Tcl_Interp *interp);
MODULE_SCOPE int	TclNamespaceEnsembleCmd(void *dummy,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_OpenObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_PackageObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_PidObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitPrefixCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_PutsObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_PwdObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ReadObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_RegexpObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_RegsubObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_RenameObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_RepresentationCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ReturnObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ScanObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SeekObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SetObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SplitObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SocketObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SourceObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE Tcl_Command TclInitStringCmd(Tcl_Interp *interp);
MODULE_SCOPE int	Tcl_SubstObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_SwitchObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TellObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_ThrowObjCmd(void *dummy, Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TimeObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TimeRateObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TraceObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_TryObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UnloadObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UnsetObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UpdateObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UplevelObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_UpvarObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_VariableObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_VwaitObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	Tcl_WhileObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------
 * Compilation procedures for commands in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclCompileAppendCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileArrayExistsCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileArraySetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileArrayUnsetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBreakCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileCatchCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileClockClicksCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileClockReadingCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileConcatCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileContinueCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictAppendCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictCreateCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictExistsCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictForCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictGetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictGetWithDefaultCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictIncrCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictLappendCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictMapCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictMergeCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictSetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictUnsetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictUpdateCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileDictWithCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileEnsemble(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileErrorCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileExprCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileForCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileForeachCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileFormatCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileGlobalCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileIfCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoCommandsCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoCoroutineCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoExistsCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoLevelCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoObjectClassCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoObjectIsACmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileInfoObjectNamespaceCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileIncrCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLappendCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLassignCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLindexCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLinsertCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileListCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLlengthCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLmapCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLrangeCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLreplaceCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLsetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceCodeCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceCurrentCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceOriginCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceQualifiersCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceTailCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceUpvarCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNamespaceWhichCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileNoOp(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileObjectNextCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileObjectNextToCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileObjectSelfCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileRegexpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileRegsubCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileReturnCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringCatCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringCmpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringEqualCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringFirstCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringIndexCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringInsertCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringIsCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringLastCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringLenCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringMapCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringMatchCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringRangeCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringReplaceCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringToLowerCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringToTitleCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringToUpperCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringTrimCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringTrimLCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringTrimRCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSubstCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSwitchCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileTailcallCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileThrowCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileTryCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileUnsetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileUpvarCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileVariableCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileWhileCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileYieldCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileYieldToCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic0ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic1ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic2ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic3ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic0Or1ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic1Or2ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic2Or3ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic0To2ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasic1To3ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasicMin0ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasicMin1ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileBasicMin2ArgCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);

MODULE_SCOPE int	TclInvertOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileInvertOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclNotOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileNotOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclAddOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileAddOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclMulOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileMulOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclAndOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileAndOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclOrOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileOrOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclXorOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileXorOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclPowOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompilePowOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclLshiftOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileLshiftOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclRshiftOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileRshiftOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclModOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileModOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclNeqOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileNeqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclStrneqOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileStrneqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclInOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileInOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclNiOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileNiOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclMinusOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileMinusOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclDivOpCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE int	TclCompileDivOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLessOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileLeqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileGreaterOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileGeqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileEqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStreqOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStrLtOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStrLeOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStrGtOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStrGeOpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);

MODULE_SCOPE int	TclCompileAssembleCmd(Tcl_Interp *interp,
			    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,
			    Tcl_Obj *const objv[], int flags);
MODULE_SCOPE Tcl_Obj *	TclStringFirst(Tcl_Obj *needle, Tcl_Obj *haystack,
			    size_t start);
MODULE_SCOPE Tcl_Obj *	TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack,
			    size_t last);
MODULE_SCOPE Tcl_Obj *	TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    size_t count, int flags);
MODULE_SCOPE Tcl_Obj *	TclStringReplace(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    size_t first, size_t 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);
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,
			    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);
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);
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);
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,
			    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.







<
|


<










<
<
<
<
<
<




|
|




<
<
<




|
<
|
<

|
|
|
|
|
<












<

|

>
>
>
>





|
>

|
|

>
>
>
|
|



|



|












|




|
<
<


|

|
|


>


|
>
>
>
>

|
>
>
>
>
>
>
>

>


>


>
>
>
>
>






|
|

|

>





<
<



|

|













|
>
|














|

|



|










|


|


|
<
<
<
|




|

|


|


|
|
|
|
|
|
|
|

>
>
>





<
<
<
<
<
<
<
<
|
<
<
<
<
<

















|
|




|





|







|

|
|
>

















|
<
<
|
<
<
|
<
<


|
<
<
|
<
<
|
<
<

|
<
<
|
<
<
|
<
|
<

|
<
|
|
<
<
|
<
<
|
<
<



|
<
<






|
|
<
<


|
<
<
|
<
<

|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<

|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<

|
<
|
|
<
<
|
<
|
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<

|
<
<
|
<
<
|
<
<
|
<
<

|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<

|
<
<
|
<
<
|
<
<
|
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<







|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
|
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<

|
<
<
|
|
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<

|
<
<






|


|

|

|

|
















|
|


|
|



|



|



|





|







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
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);
MODULE_SCOPE int	TclNREvalFile(Tcl_Interp *interp, Tcl_Obj *pathPtr,
			    const char *encodingName);

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 Tcl_Obj *	TclGetProcessGlobalValue(ProcessGlobalValue *pgvPtr);
MODULE_SCOPE Tcl_Obj *	TclGetSourceFromFrame(CmdFrame *cfPtr, int objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE char *	TclGetStringStorage(Tcl_Obj *objPtr,
			    Tcl_Size *sizePtr);
MODULE_SCOPE int	TclGetLoadedLibraries(Tcl_Interp *interp,
				const char *targetName,
				const char *packageName);
MODULE_SCOPE int	TclGetWideBitsFromObj(Tcl_Interp *, Tcl_Obj *,
				Tcl_WideInt *);



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 Tcl_ObjCmdProc TclInfoExistsCmd;

MODULE_SCOPE Tcl_ObjCmdProc TclInfoCoroutineCmd;

MODULE_SCOPE Tcl_Obj *	TclInfoFrame(Tcl_Interp *interp, CmdFrame *framePtr);
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;

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	TclIsBareword(int byte);
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,
			    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, 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_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,
			    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 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 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,
			    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,
			    Tcl_Size numBytes, Tcl_Size *readPtr, char *dst);


MODULE_SCOPE int	TclParseNumber(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    const char *expected, const char *bytes,
			    Tcl_Size numBytes, const char **endPtrPtr, int flags);
MODULE_SCOPE void	TclParseInit(Tcl_Interp *interp, const char *string,
			    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 int	TclNewArithSeriesObj(Tcl_Interp *interp, Tcl_Obj **arithSeriesPtr,
                            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,
			    Tcl_Size len);
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
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,
			    TCL_HASH_TYPE stackSize, int flags);
MODULE_SCOPE Tcl_Size	TclpFindVariable(const char *name, Tcl_Size *lengthPtr);
MODULE_SCOPE void	TclpInitLibraryPath(char **valuePtr,
			    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	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, Tcl_Size *lenPtr);
MODULE_SCOPE Tcl_PathType TclpGetNativePathType(Tcl_Obj *pathPtr,
			    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 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,
			    Tcl_Size reStrLen, Tcl_DString *dsPtr, int *flagsPtr,
			    int *quantifiersFoundPtr);
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	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);
MODULE_SCOPE void	TclSignalExitThread(Tcl_ThreadId id, int result);
MODULE_SCOPE void	TclSpellFix(Tcl_Interp *interp,
			    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,
			    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, Tcl_Size reqlength);



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,
			    Tcl_Size numBytes, int flags, Tcl_Size line,
			    struct CompileEnv *envPtr);
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,
			    Tcl_Size numBytes, int flags, Tcl_Parse *parsePtr,
			    Tcl_InterpState *statePtr);
MODULE_SCOPE int	TclSubstTokens(Tcl_Interp *interp, Tcl_Token *tokenPtr,
			    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 int	TclUtfCount(int ch);





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 int	TclpLoadMemory(Tcl_Interp *interp, void *buffer,
			    int size, int 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 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 long long TclpGetWideClicks(void);
MODULE_SCOPE double	TclpWideClickInMicrosec(void);
#	define		TclpWideClicksToNanoseconds(clicks) \
				((double)(clicks) * TclpWideClickInMicrosec() * 1000)
#   endif
#endif
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, Tcl_Size length);
/* Tip 430 */
MODULE_SCOPE int	TclZipfs_Init(Tcl_Interp *interp);
MODULE_SCOPE int	TclIsZipfsPath(const char *path);
MODULE_SCOPE void	TclZipfsFinalize(void);

/*
 * Many parsing tasks need a common definition of whitespace.
 * Use this routine and macro to achieve that and place
 * optimization (fragile on changes) in one place.
 */

MODULE_SCOPE int	TclIsSpaceProc(int byte);
#	define TclIsSpaceProcM(byte) \
		(((byte) > 0x20) ? 0 : TclIsSpaceProc(byte))

/*
 *----------------------------------------------------------------
 * Command procedures in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE Tcl_ObjCmdProc Tcl_AfterObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_AppendObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ApplyObjCmd;


MODULE_SCOPE Tcl_Command TclInitArrayCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_Command TclInitBinaryCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc Tcl_BreakObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_CatchObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_CdObjCmd;


MODULE_SCOPE Tcl_Command TclInitChanCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc TclChanCreateObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclChanPostEventObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclChanPopObjCmd;

MODULE_SCOPE Tcl_ObjCmdProc TclChanPushObjCmd;

MODULE_SCOPE void	TclClockInit(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc TclClockOldscanObjCmd;

MODULE_SCOPE Tcl_ObjCmdProc Tcl_CloseObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_ConcatObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ConstObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ContinueObjCmd;


MODULE_SCOPE Tcl_TimerToken TclCreateAbsoluteTimerHandler(
			    Tcl_Time *timePtr, Tcl_TimerProc *proc,
			    void *clientData);
MODULE_SCOPE Tcl_ObjCmdProc TclDefaultBgErrorHandlerObjCmd;


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,
			    Tcl_Size pathc, Tcl_Obj *const pathv[]);
MODULE_SCOPE Tcl_ObjCmdProc Tcl_DisassembleObjCmd;



/* Assemble command function */
MODULE_SCOPE Tcl_ObjCmdProc Tcl_AssembleObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclNRAssembleObjCmd;


MODULE_SCOPE Tcl_Command TclInitEncodingCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc Tcl_EofObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ErrorObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_EvalObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ExecObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ExitObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ExprObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_FblockedObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_FconfigureObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_FcopyObjCmd;


MODULE_SCOPE Tcl_Command TclInitFileCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc Tcl_FileEventObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_FlushObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ForObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ForeachObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_FormatObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_GetsObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_GlobalObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_GlobObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_IfObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_IncrObjCmd;


MODULE_SCOPE Tcl_Command TclInitInfoCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc Tcl_InterpObjCmd;

MODULE_SCOPE Tcl_ObjCmdProc Tcl_JoinObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LappendObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LassignObjCmd;

MODULE_SCOPE Tcl_ObjCmdProc Tcl_LeditObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc Tcl_LindexObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LinsertObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LlengthObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ListObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LmapObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LoadObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LpopObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LrangeObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LremoveObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LrepeatObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LreplaceObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LreverseObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LsearchObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LseqObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LsetObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_LsortObjCmd;


MODULE_SCOPE Tcl_Command TclInitNamespaceCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc TclNamespaceEnsembleCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_OpenObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_PackageObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_PidObjCmd;


MODULE_SCOPE Tcl_Command TclInitPrefixCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc Tcl_PutsObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_PwdObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ReadObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_RegexpObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_RegsubObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_RenameObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_RepresentationCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ReturnObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ScanObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_SeekObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_SetObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_SplitObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_SocketObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_SourceObjCmd;


MODULE_SCOPE Tcl_Command TclInitStringCmd(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc Tcl_SubstObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_SwitchObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_TellObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_ThrowObjCmd;

MODULE_SCOPE Tcl_ObjCmdProc Tcl_TimeObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_TimeRateObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_TraceObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_TryObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_UnloadObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_UnsetObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_UpdateObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_UplevelObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_UpvarObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_VariableObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_VwaitObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc Tcl_WhileObjCmd;



/*
 *----------------------------------------------------------------
 * Compilation procedures for commands in the generic core:
 *----------------------------------------------------------------
 */

MODULE_SCOPE CompileProc TclCompileAppendCmd;


MODULE_SCOPE CompileProc TclCompileArrayExistsCmd;


MODULE_SCOPE CompileProc TclCompileArraySetCmd;


MODULE_SCOPE CompileProc TclCompileArrayUnsetCmd;


MODULE_SCOPE CompileProc TclCompileBreakCmd;


MODULE_SCOPE CompileProc TclCompileCatchCmd;


MODULE_SCOPE CompileProc TclCompileClockClicksCmd;


MODULE_SCOPE CompileProc TclCompileClockReadingCmd;


MODULE_SCOPE CompileProc TclCompileConcatCmd;

MODULE_SCOPE CompileProc TclCompileConstCmd;
MODULE_SCOPE CompileProc TclCompileContinueCmd;


MODULE_SCOPE CompileProc TclCompileDictAppendCmd;


MODULE_SCOPE CompileProc TclCompileDictCreateCmd;


MODULE_SCOPE CompileProc TclCompileDictExistsCmd;


MODULE_SCOPE CompileProc TclCompileDictForCmd;


MODULE_SCOPE CompileProc TclCompileDictGetCmd;


MODULE_SCOPE CompileProc TclCompileDictGetWithDefaultCmd;


MODULE_SCOPE CompileProc TclCompileDictIncrCmd;


MODULE_SCOPE CompileProc TclCompileDictLappendCmd;


MODULE_SCOPE CompileProc TclCompileDictMapCmd;


MODULE_SCOPE CompileProc TclCompileDictMergeCmd;


MODULE_SCOPE CompileProc TclCompileDictSetCmd;


MODULE_SCOPE CompileProc TclCompileDictUnsetCmd;


MODULE_SCOPE CompileProc TclCompileDictUpdateCmd;


MODULE_SCOPE CompileProc TclCompileDictWithCmd;


MODULE_SCOPE CompileProc TclCompileEnsemble;


MODULE_SCOPE CompileProc TclCompileErrorCmd;


MODULE_SCOPE CompileProc TclCompileExprCmd;


MODULE_SCOPE CompileProc TclCompileForCmd;


MODULE_SCOPE CompileProc TclCompileForeachCmd;


MODULE_SCOPE CompileProc TclCompileFormatCmd;


MODULE_SCOPE CompileProc TclCompileGlobalCmd;


MODULE_SCOPE CompileProc TclCompileIfCmd;


MODULE_SCOPE CompileProc TclCompileInfoCommandsCmd;


MODULE_SCOPE CompileProc TclCompileInfoCoroutineCmd;


MODULE_SCOPE CompileProc TclCompileInfoExistsCmd;


MODULE_SCOPE CompileProc TclCompileInfoLevelCmd;


MODULE_SCOPE CompileProc TclCompileInfoObjectClassCmd;


MODULE_SCOPE CompileProc TclCompileInfoObjectIsACmd;


MODULE_SCOPE CompileProc TclCompileInfoObjectNamespaceCmd;


MODULE_SCOPE CompileProc TclCompileIncrCmd;


MODULE_SCOPE CompileProc TclCompileLappendCmd;


MODULE_SCOPE CompileProc TclCompileLassignCmd;


MODULE_SCOPE CompileProc TclCompileLindexCmd;


MODULE_SCOPE CompileProc TclCompileLinsertCmd;


MODULE_SCOPE CompileProc TclCompileListCmd;


MODULE_SCOPE CompileProc TclCompileLlengthCmd;


MODULE_SCOPE CompileProc TclCompileLmapCmd;


MODULE_SCOPE CompileProc TclCompileLrangeCmd;


MODULE_SCOPE CompileProc TclCompileLreplaceCmd;


MODULE_SCOPE CompileProc TclCompileLsetCmd;


MODULE_SCOPE CompileProc TclCompileNamespaceCodeCmd;


MODULE_SCOPE CompileProc TclCompileNamespaceCurrentCmd;


MODULE_SCOPE CompileProc TclCompileNamespaceOriginCmd;


MODULE_SCOPE CompileProc TclCompileNamespaceQualifiersCmd;


MODULE_SCOPE CompileProc TclCompileNamespaceTailCmd;


MODULE_SCOPE CompileProc TclCompileNamespaceUpvarCmd;


MODULE_SCOPE CompileProc TclCompileNamespaceWhichCmd;


MODULE_SCOPE CompileProc TclCompileNoOp;


MODULE_SCOPE CompileProc TclCompileObjectNextCmd;


MODULE_SCOPE CompileProc TclCompileObjectNextToCmd;


MODULE_SCOPE CompileProc TclCompileObjectSelfCmd;


MODULE_SCOPE CompileProc TclCompileRegexpCmd;


MODULE_SCOPE CompileProc TclCompileRegsubCmd;


MODULE_SCOPE CompileProc TclCompileReturnCmd;


MODULE_SCOPE CompileProc TclCompileSetCmd;


MODULE_SCOPE CompileProc TclCompileStringCatCmd;


MODULE_SCOPE CompileProc TclCompileStringCmpCmd;


MODULE_SCOPE CompileProc TclCompileStringEqualCmd;


MODULE_SCOPE CompileProc TclCompileStringFirstCmd;


MODULE_SCOPE CompileProc TclCompileStringIndexCmd;


MODULE_SCOPE CompileProc TclCompileStringInsertCmd;


MODULE_SCOPE CompileProc TclCompileStringIsCmd;


MODULE_SCOPE CompileProc TclCompileStringLastCmd;


MODULE_SCOPE CompileProc TclCompileStringLenCmd;


MODULE_SCOPE CompileProc TclCompileStringMapCmd;


MODULE_SCOPE CompileProc TclCompileStringMatchCmd;


MODULE_SCOPE CompileProc TclCompileStringRangeCmd;


MODULE_SCOPE CompileProc TclCompileStringReplaceCmd;


MODULE_SCOPE CompileProc TclCompileStringToLowerCmd;


MODULE_SCOPE CompileProc TclCompileStringToTitleCmd;


MODULE_SCOPE CompileProc TclCompileStringToUpperCmd;


MODULE_SCOPE CompileProc TclCompileStringTrimCmd;


MODULE_SCOPE CompileProc TclCompileStringTrimLCmd;


MODULE_SCOPE CompileProc TclCompileStringTrimRCmd;


MODULE_SCOPE CompileProc TclCompileSubstCmd;


MODULE_SCOPE CompileProc TclCompileSwitchCmd;


MODULE_SCOPE CompileProc TclCompileTailcallCmd;


MODULE_SCOPE CompileProc TclCompileThrowCmd;


MODULE_SCOPE CompileProc TclCompileTryCmd;


MODULE_SCOPE CompileProc TclCompileUnsetCmd;


MODULE_SCOPE CompileProc TclCompileUpvarCmd;


MODULE_SCOPE CompileProc TclCompileVariableCmd;


MODULE_SCOPE CompileProc TclCompileWhileCmd;


MODULE_SCOPE CompileProc TclCompileYieldCmd;


MODULE_SCOPE CompileProc TclCompileYieldToCmd;


MODULE_SCOPE CompileProc TclCompileBasic0ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasic1ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasic2ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasic3ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasic0Or1ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasic1Or2ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasic2Or3ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasic0To2ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasic1To3ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasicMin0ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasicMin1ArgCmd;


MODULE_SCOPE CompileProc TclCompileBasicMin2ArgCmd;



MODULE_SCOPE Tcl_ObjCmdProc TclInvertOpCmd;


MODULE_SCOPE CompileProc TclCompileInvertOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclNotOpCmd;


MODULE_SCOPE CompileProc TclCompileNotOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclAddOpCmd;


MODULE_SCOPE CompileProc TclCompileAddOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclMulOpCmd;


MODULE_SCOPE CompileProc TclCompileMulOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclAndOpCmd;


MODULE_SCOPE CompileProc TclCompileAndOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclOrOpCmd;


MODULE_SCOPE CompileProc TclCompileOrOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclXorOpCmd;


MODULE_SCOPE CompileProc TclCompileXorOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclPowOpCmd;


MODULE_SCOPE CompileProc TclCompilePowOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclLshiftOpCmd;


MODULE_SCOPE CompileProc TclCompileLshiftOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclRshiftOpCmd;


MODULE_SCOPE CompileProc TclCompileRshiftOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclModOpCmd;


MODULE_SCOPE CompileProc TclCompileModOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclNeqOpCmd;


MODULE_SCOPE CompileProc TclCompileNeqOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclStrneqOpCmd;


MODULE_SCOPE CompileProc TclCompileStrneqOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclInOpCmd;


MODULE_SCOPE CompileProc TclCompileInOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclNiOpCmd;


MODULE_SCOPE CompileProc TclCompileNiOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclMinusOpCmd;


MODULE_SCOPE CompileProc TclCompileMinusOpCmd;


MODULE_SCOPE Tcl_ObjCmdProc TclDivOpCmd;


MODULE_SCOPE CompileProc TclCompileDivOpCmd;


MODULE_SCOPE CompileProc TclCompileLessOpCmd;


MODULE_SCOPE CompileProc TclCompileLeqOpCmd;


MODULE_SCOPE CompileProc TclCompileGreaterOpCmd;


MODULE_SCOPE CompileProc TclCompileGeqOpCmd;


MODULE_SCOPE CompileProc TclCompileEqOpCmd;


MODULE_SCOPE CompileProc TclCompileStreqOpCmd;


MODULE_SCOPE CompileProc TclCompileStrLtOpCmd;


MODULE_SCOPE CompileProc TclCompileStrLeOpCmd;


MODULE_SCOPE CompileProc TclCompileStrGtOpCmd;


MODULE_SCOPE CompileProc TclCompileStrGeOpCmd;



MODULE_SCOPE CompileProc TclCompileAssembleCmd;



/*
 * Routines that provide the [string] ensemble functionality. Possible
 * candidates for public interface.
 */

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,
			    Tcl_Size start);
MODULE_SCOPE Tcl_Obj *	TclStringLast(Tcl_Obj *needle, Tcl_Obj *haystack,
			    Tcl_Size last);
MODULE_SCOPE Tcl_Obj *	TclStringRepeat(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    Tcl_Size count, int flags);
MODULE_SCOPE Tcl_Obj *	TclStringReplace(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    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, int createPart1,
			    int createPart2, Var **arrayPtrPtr);
MODULE_SCOPE Var *	TclLookupArrayElement(Tcl_Interp *interp,
			    Tcl_Obj *arrayNamePtr, Tcl_Obj *elNamePtr,
			    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, 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,
			    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,
			    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, 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.
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

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);

/*
 * 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);








/* Constants used in index value encoding routines. */
#define TCL_INDEX_END           ((size_t)-2)
#define TCL_INDEX_START         ((size_t)0)
































/*
 *----------------------------------------------------------------
 * 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







>













|
|

>
>
>
>
>
>
>

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

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);

/*
 * 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,
			    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           ((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
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
 * 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))

#  define TclFreeObjStorageEx(interp, objPtr) \
	Tcl_Free(objPtr)

#undef USE_THREAD_ALLOC
#undef USE_TCLALLOC
#elif TCL_THREADS && defined(USE_THREAD_ALLOC)







|







4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
 * 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))

#  define TclFreeObjStorageEx(interp, objPtr) \
	Tcl_Free(objPtr)

#undef USE_THREAD_ALLOC
#undef USE_TCLALLOC
#elif TCL_THREADS && defined(USE_THREAD_ALLOC)
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

# 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:
 *

 * MODULE_SCOPE void TclInitStringRep(Tcl_Obj *objPtr, char *bytePtr, size_t len);

 *
 * This macro should only be called on an unshared objPtr where
 *  objPtr->typePtr->freeIntRepProc == NULL
 *----------------------------------------------------------------
 */





#define TclInitStringRep(objPtr, bytePtr, len) \
    if ((len) == 0) { \
	(objPtr)->bytes	 = &tclEmptyString; \
	(objPtr)->length = 0; \
    } else { \
	(objPtr)->bytes = (char *)Tcl_Alloc((len) + 1); \
	memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (len)); \
	(objPtr)->bytes[len] = '\0'; \
	(objPtr)->length = (len); \
    }











/*
 *----------------------------------------------------------------
 * 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 \
	    ? NULL : Tcl_GetString((objPtr)), \
	    *(lenPtr) = (objPtr)->length, (objPtr)->bytes))
#define TclGetUnicodeFromObj(objPtr, lenPtr) \
    (Tcl_GetUnicodeFromObj((objPtr), NULL), \
	    *(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);
 *----------------------------------------------------------------
 */

#define TclFreeIntRep(objPtr) \
    if ((objPtr)->typePtr != NULL) { \
	if ((objPtr)->typePtr->freeIntRepProc != NULL) { \
	    (objPtr)->typePtr->freeIntRepProc(objPtr); \
	} \
	(objPtr)->typePtr = NULL; \
    }








<
<
<





|
|
|
>
>
>
>
>
>
>
|
>
>
|

>

>

<
<


>
>
>
>



|
<

|




>
>
>
>
>
>
>
>
>
>
















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
<
|
<
|
<
<
<
<
<
<
<







|



|







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

# define TclNewObj(objPtr) \
    TclDbNewObj(objPtr, __FILE__, __LINE__);

# define TclDecrRefCount(objPtr) \
    Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__)




#undef USE_THREAD_ALLOC
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------
 * 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);
 *


 *----------------------------------------------------------------
 */

#define TclInitEmptyStringRep(objPtr) \
	((objPtr)->length = (((objPtr)->bytes = &tclEmptyString), 0))


#define TclInitStringRep(objPtr, bytePtr, len) \
    if ((len) == 0) { \
	TclInitEmptyStringRep(objPtr); \

    } else { \
	(objPtr)->bytes = (char *)Tcl_Alloc((len) + 1U); \
	memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : &tclEmptyString, (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))




















#define TclGetStringFromObj(objPtr, lenPtr) \
    ((objPtr)->bytes \

	    ? (*(lenPtr) = (objPtr)->length, (objPtr)->bytes)	\

	    : (Tcl_GetStringFromObj)((objPtr), (lenPtr)))








/*
 *----------------------------------------------------------------
 * 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	TclFreeInternalRep(Tcl_Obj *objPtr);
 *----------------------------------------------------------------
 */

#define TclFreeInternalRep(objPtr) \
    if ((objPtr)->typePtr != NULL) { \
	if ((objPtr)->typePtr->freeIntRepProc != NULL) { \
	    (objPtr)->typePtr->freeIntRepProc(objPtr); \
	} \
	(objPtr)->typePtr = NULL; \
    }

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
#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))
#define TclGrowTokenArray(tokenPtr, used, available, append, staticPtr)	\
    do {								\
	int _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_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)));	\
	    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))); \
	    }								\
	    (available) = allocated;					\
	    if (oldPtr == NULL) {					\
		memcpy(newPtr, staticPtr,				\
			((used) * sizeof(Tcl_Token)));		\
	    }								\
	    (tokenPtr) = newPtr;					\
	}								\
    } while (0)

#define TclGrowParseTokenArray(parsePtr, append)			\
    TclGrowTokenArray((parsePtr)->tokenPtr, (parsePtr)->numTokens,	\







|


|
<
<
<
<

|





<
<
<
|
|


<
<
<
|
|




|







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
#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

/* TODO - code below does not check for integer overflow */
#define TclGrowTokenArray(tokenPtr, used, available, append, staticPtr)	\
    do {								\
	Tcl_Size _needed = (used) + (append);				\




	if (_needed > (available)) {					\
	    Tcl_Size allocated = 2 * _needed;				\
	    Tcl_Token *oldPtr = (tokenPtr);				\
	    Tcl_Token *newPtr;						\
	    if (oldPtr == (staticPtr)) {				\
		oldPtr = NULL;						\
	    }								\



	    newPtr = (Tcl_Token *)Tcl_AttemptRealloc((char *) oldPtr,	\
		    allocated * sizeof(Tcl_Token));	\
	    if (newPtr == NULL) {					\
		allocated = _needed + (append) + TCL_MIN_TOKEN_GROWTH;	\



		newPtr = (Tcl_Token *)Tcl_Realloc((char *) oldPtr,	\
			allocated * sizeof(Tcl_Token)); \
	    }								\
	    (available) = allocated;					\
	    if (oldPtr == NULL) {					\
		memcpy(newPtr, staticPtr,				\
			(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
 * 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)	\
	    : 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);

 *----------------------------------------------------------------
 */

#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; \
    } 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)


/*
 *----------------------------------------------------------------
 * 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);







<




<
<
<
<
<
<








|
|
>



|

|

|







<
<
<
<
<

















|
|

|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
 * 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);
 *----------------------------------------------------------------
 */


#define TclUtfToUniChar(str, chPtr) \
	(((UCHAR(*(str))) < 0x80) ?		\
	    ((*(chPtr) = UCHAR(*(str))), 1)	\
	    : Tcl_UtfToUniChar(str, chPtr))







/*
 *----------------------------------------------------------------
 * 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	TclNumUtfCharsM(Tcl_Size numChars, const char *bytes,
 *				Tcl_Size numBytes);
 * numBytes must be >= 0
 *----------------------------------------------------------------
 */

#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);






/*
 *----------------------------------------------------------------
 * 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) && 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 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
 *----------------------------------------------------------------------
 *
 * Core procedure added to libtommath for bignum manipulation.
 *
 *----------------------------------------------------------------------
 */

MODULE_SCOPE Tcl_PackageInitProc 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;



/*
 *----------------------------------------------------------------
 * 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);







|











|
|
|
|
|
>
>







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
 *----------------------------------------------------------------------
 *
 * Core procedure added to libtommath for bignum manipulation.
 *
 *----------------------------------------------------------------------
 */

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_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);
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
 * 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);	\
    } while (0)

#define TclSetDoubleObj(objPtr, d) \
    do {						\
	Tcl_ObjIntRep ir;				\
	ir.doubleValue = (double) d;			\
	TclInvalidateStringRep(objPtr);			\
	Tcl_StoreIntRep(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	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);			\
    } while (0)

#define TclNewIndexObj(objPtr, w) \
    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);			\
    } while (0)




#define TclNewDoubleObj(objPtr, d) \
    do {							\
	TclIncrObjsAllocated();					\
	TclAllocObjStorage(objPtr);				\
	(objPtr)->refCount = 0;					\
	(objPtr)->bytes = NULL;					\







|


|




|


|










|

















|

<




>
>
>
>
>
>
>
>
|
|
>


>
>
>







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
 * 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_ObjInternalRep ir;				\
	ir.wideValue = (Tcl_WideInt) i;			\
	TclInvalidateStringRep(objPtr);			\
	Tcl_StoreInternalRep(objPtr, &tclIntType, &ir);	\
    } while (0)

#define TclSetDoubleObj(objPtr, d) \
    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, 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);			\
    } while (0)

#define TclNewUIntObj(objPtr, uw) \
    do {						\

	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;					\
4846
4847
4848
4849
4850
4851
4852
4853















4854
4855
4856
4857
4858
4859
4860
4861
4862
	(objPtr)->typePtr = NULL;				\
	TCL_DTRACE_OBJ_CREATE(objPtr);				\
    } while (0)

#else /* TCL_MEM_DEBUG */
#define TclNewIntObj(objPtr, w) \
    (objPtr) = Tcl_NewWideIntObj(w)
















#define TclNewIndexObj(objPtr, w) \
    (objPtr) = ((w) == TCL_INDEX_NONE) ? Tcl_NewWideIntObj(-1) : Tcl_NewWideIntObj(w)

#define TclNewDoubleObj(objPtr, d) \
    (objPtr) = Tcl_NewDoubleObj(d)

#define TclNewStringObj(objPtr, s, len) \
    (objPtr) = Tcl_NewStringObj((s), (len))
#endif /* TCL_MEM_DEBUG */








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







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
	(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) \
    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
 */

#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







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







4819
4820
4821
4822
4823
4824
4825


























4826
4827
4828
4829
4830
4831
4832
 */

#define TclDStringAppendLiteral(dsPtr, sLiteral) \
    Tcl_DStringAppend((dsPtr), (sLiteral), sizeof(sLiteral "") - 1)
#define TclDStringClear(dsPtr) \
    Tcl_DStringSetLength((dsPtr), 0)



























/*
 *----------------------------------------------------------------
 * Inline version of Tcl_GetCurrentNamespace and Tcl_GetGlobalNamespace.
 */

#define TclGetCurrentNamespace(interp) \
    (Tcl_Namespace *) ((Interp *)(interp))->varFramePtr->nsPtr
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
#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);					\
    } while (0)

#define TclSmallFreeEx(interp, memPtr) \
    do {								\
	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;					\
    } while (0)

#define TclSmallFreeEx(interp, memPtr) \
    do {								\
	Tcl_Obj *_objPtr = (Tcl_Obj *) memPtr;				\
	_objPtr->bytes = NULL;						\
	_objPtr->typePtr = NULL;					\
	_objPtr->refCount = 1;						\
	TclDecrRefCount(_objPtr);					\
    } while (0)
#endif   /* TCL_MEM_DEBUG */








|




|









|




|







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
#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);			\
    } while (0)

#define TclSmallFreeEx(interp, memPtr) \
    do {								\
	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;				\
    } while (0)

#define TclSmallFreeEx(interp, memPtr) \
    do {								\
	Tcl_Obj *_objPtr = (Tcl_Obj *)(memPtr);				\
	_objPtr->bytes = NULL;						\
	_objPtr->typePtr = NULL;					\
	_objPtr->refCount = 1;						\
	TclDecrRefCount(_objPtr);					\
    } while (0)
#endif   /* TCL_MEM_DEBUG */

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

#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))))
#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
#endif





























#endif /* _TCLINT */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|


















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







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

#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)))
#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
#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
/* 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);
/* 6 */
EXTERN void		TclCleanupCommand(Command *cmdPtr);
/* 7 */
EXTERN size_t		TclCopyAndCollapse(size_t count, const char *src,
				char *dst);
/* Slot 8 is reserved */
/* 9 */
EXTERN int		TclCreatePipeline(Tcl_Interp *interp, int 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);







|
>
|



|



|







46
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,
				Tcl_Size numPids, Tcl_Pid *pidPtr,
				Tcl_Channel errorChan);
/* 6 */
EXTERN void		TclCleanupCommand(Command *cmdPtr);
/* 7 */
EXTERN Tcl_Size		TclCopyAndCollapse(Tcl_Size count, const char *src,
				char *dst);
/* Slot 8 is reserved */
/* 9 */
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
/* 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 **elementPtr,
				const char **nextPtr, size_t *sizePtr,
				int *bracePtr);
/* 23 */
EXTERN Proc *		TclFindProc(Interp *iPtr, const char *procName);
/* 24 */
EXTERN size_t		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 */
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);
/* 40 */
EXTERN int		TclGetOpenMode(Tcl_Interp *interp, const char *str,
				int *seekFlagPtr);
/* 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,
				Tcl_DString *bufPtr);

/* 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 */
EXTERN int		TclInvokeObjectCommand(void *clientData,
				Tcl_Interp *interp, int argc,
				const char **argv);
/* 54 */
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 */
EXTERN int		TclObjInterpProc(void *clientData,
				Tcl_Interp *interp, int objc,
				Tcl_Obj *const objv[]);
/* 64 */
EXTERN int		TclObjInvoke(Tcl_Interp *interp, int 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);
/* 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);
/* 76 */
EXTERN Tcl_WideUInt	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);
/* 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 */







|

|




|

















|
<
<








|


|





<
|
|
<
>











|
<
<
<
|
<
<
<
















|
<
<
<

|






|







|

|





|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

133
134

135
136
137
138
139
140
141
142
143
144
145
146
147



148



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165



166
167
168
169
170
171
172
173
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, Tcl_Size listLength,
				const char **elementPtr,
				const char **nextPtr, Tcl_Size *sizePtr,
				int *bracePtr);
/* 23 */
EXTERN Proc *		TclFindProc(Interp *iPtr, const char *procName);
/* 24 */
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 */
/* Slot 37 is reserved */


/* 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 Tcl_ObjCmdProc *	 TclGetObjInterpProc(void);
/* 40 */
EXTERN int		TclGetOpenMode(Tcl_Interp *interp, const char *str,
				int *modeFlagsPtr);
/* 41 */
EXTERN Tcl_Command	TclGetOriginalCommand(Tcl_Command command);
/* 42 */
EXTERN const char *	TclpGetUserHome(const char *name,
				Tcl_DString *bufferPtr);

/* 43 */
EXTERN Tcl_ObjCmdProc2 * TclGetObjInterpProc2(void);

/* 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 */
/* Slot 53 is reserved */



/* Slot 54 is reserved */



/* 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);
/* Slot 63 is reserved */



/* 64 */
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(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 unsigned long long TclpGetClicks(void);
/* 76 */
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, 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
/* 97 */
EXTERN void		TclResetShadowedCmdRefs(Tcl_Interp *interp,
				Command *newCmdPtr);
/* 98 */
EXTERN int		TclServiceIdle(void);
/* Slot 99 is reserved */
/* Slot 100 is reserved */
/* 101 */
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);
/* 111 */
EXTERN void		Tcl_AddInterpResolvers(Tcl_Interp *interp,
				const char *name,
				Tcl_ResolveCmdProc *cmdProc,
				Tcl_ResolveVarProc *varProc,
				Tcl_ResolveCompiledVarProc *compiledVarProc);
/* Slot 112 is reserved */







|
<














|







216
217
218
219
220
221
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 */
/* Slot 101 is reserved */

/* 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, 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
				const char *name);
/* 131 */
EXTERN void		Tcl_SetNamespaceResolvers(
				Tcl_Namespace *namespacePtr,
				Tcl_ResolveCmdProc *cmdProc,
				Tcl_ResolveVarProc *varProc,
				Tcl_ResolveCompiledVarProc *compiledVarProc);
/* 132 */
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);







|
<







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);
/* Slot 132 is reserved */

/* 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
/* 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		TclSetLibraryPath(Tcl_Obj *pathPtr);
/* 153 */
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,







|
|
|
<
|
<







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, Tcl_Size index,
				Tcl_Size *startPtr, Tcl_Size *endPtr);
/* Slot 152 is reserved */

/* Slot 153 is reserved */

/* 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
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 *valuePtr);
/* Slot 167 is reserved */
/* Slot 168 is reserved */
/* 169 */
EXTERN int		TclpUtfNcmp2(const char *s1, const char *s2,
				size_t n);
/* 170 */
EXTERN int		TclCheckInterpTraces(Tcl_Interp *interp,
				const char *command, size_t numChars,
				Command *cmdPtr, int result, int traceFlags,
				int objc, Tcl_Obj *const objv[]);
/* 171 */
EXTERN int		TclCheckExecutionTraces(Tcl_Interp *interp,
				const char *command, size_t numChars,
				Command *cmdPtr, int result, int traceFlags,
				int 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);
/* 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 */







|




|



|

|


|

|




|
|







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, Tcl_Size index,
				Tcl_Obj *valuePtr);
/* Slot 167 is reserved */
/* Slot 168 is reserved */
/* 169 */
EXTERN int		TclpUtfNcmp2(const void *s1, const void *s2,
				size_t n);
/* 170 */
EXTERN int		TclCheckInterpTraces(Tcl_Interp *interp,
				const char *command, Tcl_Size numChars,
				Command *cmdPtr, int result, int traceFlags,
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 171 */
EXTERN int		TclCheckExecutionTraces(Tcl_Interp *interp,
				const char *command, Tcl_Size numChars,
				Command *cmdPtr, int result, int traceFlags,
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 172 */
EXTERN int		TclInThreadExit(void);
/* 173 */
EXTERN int		TclUniCharMatch(const Tcl_UniChar *string,
				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
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);

/* 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 */


/* Slot 220 is reserved */
/* Slot 221 is reserved */


/* Slot 222 is reserved */


/* Slot 223 is reserved */

/* 224 */
EXTERN TclPlatformType * TclGetPlatform(void);
/* 225 */
EXTERN Tcl_Obj *	TclTraceDictPath(Tcl_Interp *interp,
				Tcl_Obj *rootPtr, int keyc,
				Tcl_Obj *const keyv[], int flags);
/* 226 */
EXTERN int		TclObjBeingDeleted(Tcl_Obj *objPtr);
/* 227 */
EXTERN void		TclSetNsPath(Namespace *nsPtr, size_t 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,
				const int createPart1, const 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[]);
/* 239 */
EXTERN int		TclNRInterpProcCore(Tcl_Interp *interp,
				Tcl_Obj *procNameObj, int 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,
				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_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);
/* 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);
/* 252 */
EXTERN Tcl_Obj *	TclPtrGetVar(Tcl_Interp *interp, Tcl_Var varPtr,
				Tcl_Var arrayPtr, Tcl_Obj *part1Ptr,
				Tcl_Obj *part2Ptr, const 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);
/* 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);
/* 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);
/* 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,
				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 */
    void (*tclCleanupCommand) (Command *cmdPtr); /* 6 */
    size_t (*tclCopyAndCollapse) (size_t 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 */
    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 */
    Proc * (*tclFindProc) (Interp *iPtr, const char *procName); /* 23 */
    size_t (*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 */
    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_Command (*tclGetOriginalCommand) (Tcl_Command command); /* 41 */
    const char * (*tclpGetUserHome) (const char *name, Tcl_DString *bufferPtr); /* 42 */

    void (*reserved43)(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 */
    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 (*reserved65)(void);
    void (*reserved66)(void);
    void (*reserved67)(void);
    void (*reserved68)(void);
    void * (*tclpAlloc) (size_t 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 */
    void (*reserved77)(void);
    void (*reserved78)(void);
    void (*reserved79)(void);
    void (*reserved80)(void);
    void * (*tclpRealloc) (void *ptr, size_t 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 (*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 */
    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);







|
>









|
>
>

|
>
>
|
>
>
|
>




|




|








|
<
|



















|


|








|










|







|








|



|




|




|







|

|
|
|
|
|
|
|
|
|
<
<
<
<










|

|

|












|

|












|

|
|


>
|
<








|
|








|
|




|





|
|




|



















|








|







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,
				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);
/* 219 */
EXTERN Tcl_Obj *	TclpCreateTemporaryDirectory(Tcl_Obj *dirObj,
				Tcl_Obj *basenameObj);
/* Slot 220 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, Tcl_Size keyc,
				Tcl_Obj *const keyv[], int flags);
/* 226 */
EXTERN int		TclObjBeingDeleted(Tcl_Obj *objPtr);
/* 227 */
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 createPart1,

				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,
				Tcl_Size objc, Tcl_Obj *const objv[]);
/* 239 */
EXTERN int		TclNRInterpProcCore(Tcl_Interp *interp,
				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, 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,
				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,
				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,
				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, 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,
				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,
				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, int flags);
/* 257 */
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);





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, Tcl_Size numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 5 */
    void (*tclCleanupCommand) (Command *cmdPtr); /* 6 */
    Tcl_Size (*tclCopyAndCollapse) (Tcl_Size count, const char *src, char *dst); /* 7 */
    void (*reserved8)(void);
    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, Tcl_Size listLength, const char **elementPtr, const char **nextPtr, Tcl_Size *sizePtr, int *bracePtr); /* 22 */
    Proc * (*tclFindProc) (Interp *iPtr, const char *procName); /* 23 */
    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);
    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 */
    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 (*reserved44)(void);

    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);
    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 */
    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) (TCL_HASH_TYPE size); /* 69 */
    void (*reserved70)(void);
    void (*reserved71)(void);
    void (*reserved72)(void);
    void (*reserved73)(void);
    void (*tclpFree) (void *ptr); /* 74 */
    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, 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);
    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, 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
    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 (*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 (*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 */
    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 (*tclInThreadExit) (void); /* 172 */
    int (*tclUniCharMatch) (const Tcl_UniChar *string, size_t strLen, const Tcl_UniChar *pattern, size_t 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);







|


















|
|
|












|


|
|
|

|







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 */
    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, 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, Tcl_Size index, Tcl_Obj *valuePtr); /* 166 */
    void (*reserved167)(void);
    void (*reserved168)(void);
    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, 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
    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 (*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);
    void (*reserved220)(void);
    void (*reserved221)(void);
    void (*reserved222)(void);
    void (*reserved223)(void);
    TclPlatformType * (*tclGetPlatform) (void); /* 224 */
    Tcl_Obj * (*tclTraceDictPath) (Tcl_Interp *interp, Tcl_Obj *rootPtr, int 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 (*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 */
    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 (*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 */
    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 */
    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 */
    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 (*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 */

} TclIntStubs;

extern const TclIntStubs *tclIntStubsPtr;

#ifdef __cplusplus
}
#endif







|



|

|
|
|

|

|


|







|
|


|



|

|


|
|
|
|

|
|
|
|
|
>







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, 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 */
    Tcl_Obj * (*tclpCreateTemporaryDirectory) (Tcl_Obj *dirObj, Tcl_Obj *basenameObj); /* 219 */
    void (*reserved220)(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, Tcl_Size keyc, Tcl_Obj *const keyv[], int flags); /* 225 */
    int (*tclObjBeingDeleted) (Tcl_Obj *objPtr); /* 226 */
    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, 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, 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, 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, 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, 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, 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, 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
	(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 \
	(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 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 */
#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 \
	(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 \







|
<










<
|
|
>











|
|
<
<













|
<







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 */
/* Slot 37 is reserved */

#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 */

#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 */
/* Slot 53 is reserved */
/* Slot 54 is reserved */


#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 */
/* Slot 63 is reserved */

#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
	(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 */
#define TclSetupEnv \
	(tclIntStubsPtr->tclSetupEnv) /* 102 */
#define TclSockGetPort \
	(tclIntStubsPtr->tclSockGetPort) /* 103 */
/* Slot 104 is reserved */
/* Slot 105 is reserved */
/* Slot 106 is reserved */







<
|







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 */

/* 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
	(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 133 is reserved */
/* Slot 134 is reserved */
/* Slot 135 is reserved */
/* Slot 136 is reserved */
/* Slot 137 is reserved */
#define TclGetEnv \
	(tclIntStubsPtr->tclGetEnv) /* 138 */







<
|







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 */

/* 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
	(tclIntStubsPtr->tclHandlePreserve) /* 148 */
#define TclHandleRelease \
	(tclIntStubsPtr->tclHandleRelease) /* 149 */
#define TclRegAbout \
	(tclIntStubsPtr->tclRegAbout) /* 150 */
#define TclRegExpRangeUniChar \
	(tclIntStubsPtr->tclRegExpRangeUniChar) /* 151 */
#define TclSetLibraryPath \
	(tclIntStubsPtr->tclSetLibraryPath) /* 152 */
#define TclGetLibraryPath \
	(tclIntStubsPtr->tclGetLibraryPath) /* 153 */
/* Slot 154 is reserved */
/* Slot 155 is reserved */
#define TclRegError \
	(tclIntStubsPtr->tclRegError) /* 156 */
#define TclVarTraceExists \
	(tclIntStubsPtr->tclVarTraceExists) /* 157 */
/* Slot 158 is reserved */







<
|
<
|







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 */

/* Slot 152 is reserved */

/* 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
	(tclIntStubsPtr->tclStackAlloc) /* 215 */
#define TclStackFree \
	(tclIntStubsPtr->tclStackFree) /* 216 */
#define TclPushStackFrame \
	(tclIntStubsPtr->tclPushStackFrame) /* 217 */
#define TclPopStackFrame \
	(tclIntStubsPtr->tclPopStackFrame) /* 218 */

/* Slot 219 is reserved */
/* Slot 220 is reserved */

/* Slot 221 is reserved */

/* Slot 222 is reserved */

/* Slot 223 is reserved */
#define TclGetPlatform \
	(tclIntStubsPtr->tclGetPlatform) /* 224 */
#define TclTraceDictPath \
	(tclIntStubsPtr->tclTraceDictPath) /* 225 */
#define TclObjBeingDeleted \
	(tclIntStubsPtr->tclObjBeingDeleted) /* 226 */
#define TclSetNsPath \







>
|

>
|
>
|
>
|







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 \
	(tclIntStubsPtr->tclpCreateTemporaryDirectory) /* 219 */
/* Slot 220 is reserved */
#define TclListTestObj \
	(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
	(tclIntStubsPtr->tclPtrSetVar) /* 253 */
#define TclPtrIncrObjVar \
	(tclIntStubsPtr->tclPtrIncrObjVar) /* 254 */
#define TclPtrObjMakeUpvar \
	(tclIntStubsPtr->tclPtrObjMakeUpvar) /* 255 */
#define TclPtrUnsetVar \
	(tclIntStubsPtr->tclPtrUnsetVar) /* 256 */
#define TclStaticPackage \
	(tclIntStubsPtr->tclStaticPackage) /* 257 */
#define TclpCreateTemporaryDirectory \
	(tclIntStubsPtr->tclpCreateTemporaryDirectory) /* 258 */
#define TclAppendUnicodeToObj \
	(tclIntStubsPtr->tclAppendUnicodeToObj) /* 259 */

#define TclGetBytesFromObj \
	(tclIntStubsPtr->tclGetBytesFromObj) /* 260 */

#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)
#endif /* defined(USE_TCL_STUBS) */
















#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLINTDECLS */







|
|
<
|
<
|
>
|
|






|
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





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 TclStaticLibrary \
	(tclIntStubsPtr->tclStaticLibrary) /* 257 */

/* Slot 258 is reserved */

/* 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_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

/*
 * 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. */

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Exported function declarations:







|







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.
 */

#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
/* 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 */
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 */
/* Slot 12 is reserved */
/* Slot 13 is reserved */
/* 14 */
EXTERN int		TclUnixCopyFile(const char *src, const char *dst,
				const Tcl_StatBuf *statBufPtr,
				int dontCopyAtts);







|
<








|
>







53
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);
/* Slot 5 is reserved */

/* 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);
/* 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
				Tcl_StatBuf *statBufPtr,
				Tcl_GlobTypeData *types);
/* 19 */
EXTERN void		TclMacOSXNotifierAddRunLoopMode(
				const void *runLoopMode);
/* Slot 20 is reserved */
/* Slot 21 is reserved */
/* 22 */
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 */
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);
/* Slot 9 is reserved */
/* Slot 10 is reserved */
/* 11 */
EXTERN void		TclGetAndDetachPids(Tcl_Interp *interp,
				Tcl_Channel chan);
/* 12 */
EXTERN int		TclpCloseFile(TclFile file);







|
<














|
<










|







93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108
109
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 */
/* Slot 22 is reserved */

/* 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 */
/* Slot 0 is reserved */

/* 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 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
				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);
/* 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 */







|







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, 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
/* 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 */
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 */
/* 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,







|
<








|
|
<







185
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);
/* Slot 5 is reserved */

/* 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);
/* 10 */
EXTERN Tcl_DirEntry *	TclpReaddir(TclDIR *dir);

/* 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
				Tcl_StatBuf *statBufPtr,
				Tcl_GlobTypeData *types);
/* 19 */
EXTERN void		TclMacOSXNotifierAddRunLoopMode(
				const void *runLoopMode);
/* Slot 20 is reserved */
/* Slot 21 is reserved */
/* 22 */
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 */







|
<







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 */
/* Slot 22 is reserved */

/* 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
    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);
    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 */







|







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 */
    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
    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 (*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 */
    void (*reserved9)(void);
    void (*reserved10)(void);
    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 (*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 */







|







|

|









|







276
277
278
279
280
281
282
283
284
285
286
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 (*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);
    Tcl_Size (*tclpGetPid) (Tcl_Pid pid); /* 8 */
    void (*reserved9)(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, 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
    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);
    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 */







|







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 */
    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
	(tclIntPlatStubsPtr->tclpCloseFile) /* 1 */
#define TclpCreateCommandChannel \
	(tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 2 */
#define TclpCreatePipe \
	(tclIntPlatStubsPtr->tclpCreatePipe) /* 3 */
#define TclpCreateProcess \
	(tclIntPlatStubsPtr->tclpCreateProcess) /* 4 */
#define TclUnixWaitForFile_ \
	(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 */

/* 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_ \
	(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 \
	(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 */







|
<








|
>

















|
<












|
<







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 */
/* Slot 5 is reserved */

#define TclpMakeFile \
	(tclIntPlatStubsPtr->tclpMakeFile) /* 6 */
#define TclpOpenFile \
	(tclIntPlatStubsPtr->tclpOpenFile) /* 7 */
#define TclUnixWaitForFile \
	(tclIntPlatStubsPtr->tclUnixWaitForFile) /* 8 */
#define TclpCreateTempFile \
	(tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */
#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 */
/* Slot 22 is reserved */

/* 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 */
/* Slot 0 is reserved */

/* 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
	(tclIntPlatStubsPtr->tclpCloseFile) /* 1 */
#define TclpCreateCommandChannel \
	(tclIntPlatStubsPtr->tclpCreateCommandChannel) /* 2 */
#define TclpCreatePipe \
	(tclIntPlatStubsPtr->tclpCreatePipe) /* 3 */
#define TclpCreateProcess \
	(tclIntPlatStubsPtr->tclpCreateProcess) /* 4 */
#define TclUnixWaitForFile_ \
	(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 */

/* 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_ \
	(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) */













































































































































































/* !END!: Do not edit above this line. */


#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 */

















#undef TclMacOSXGetFileAttribute /* 15 */
#undef TclMacOSXSetFileAttribute /* 16 */
#undef TclMacOSXCopyFileAttributes /* 17 */
#undef TclMacOSXMatchType /* 18 */
#undef TclMacOSXNotifierAddRunLoopMode /* 19 */
#endif

#if !defined(_WIN32)













#   undef TclpGetPid
#   define TclpGetPid(pid) ((size_t)(pid))
#endif

#endif /* _TCLINTPLATDECLS */







|
<








|
>

















|
<














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>



<

<
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|
>
>
>
>
>
>
>
>
>
>
>
>
>

|



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 */
/* Slot 5 is reserved */

#define TclpMakeFile \
	(tclIntPlatStubsPtr->tclpMakeFile) /* 6 */
#define TclpOpenFile \
	(tclIntPlatStubsPtr->tclpOpenFile) /* 7 */
#define TclUnixWaitForFile \
	(tclIntPlatStubsPtr->tclUnixWaitForFile) /* 8 */
#define TclpCreateTempFile \
	(tclIntPlatStubsPtr->tclpCreateTempFile) /* 9 */
#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 */
/* Slot 22 is reserved */

/* 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




#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(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) ((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
/*
 * 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
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|
|







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 © 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"

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
				 * 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
				 * prefix. */
} Alias;

/*
 *
 * Child:
 *







|







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
				 * 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
				 * accommodate the remaining objects in the
				 * prefix. */
} Alias;

/*
 *
 * Child:
 *
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
 * 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. */
    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.
 *      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.
 */

#define LIMIT_HANDLER_ACTIVE    0x01







|










|







182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
 * TIP#143 limit handler internal representation.
 */

struct LimitHandler {
    int flags;			/* The state of this particular handler. */
    Tcl_LimitHandlerProc *handlerProc;
				/* 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.
 *      LIMIT_HANDLER_ACTIVE - Whether the handler is currently being
 *              processed; handlers are never to be reentered.
 *      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.
 */

#define LIMIT_HANDLER_ACTIVE    0x01
261
262
263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
static int		ChildTimeLimitCmd(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, int consumedObjc,
			    int 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,
			    Tcl_Interp *interp);
static void		DeleteScriptLimitCallback(ClientData clientData);

static void		RunLimitHandlers(LimitHandler *handlerPtr,
			    Tcl_Interp *interp);
static void		TimeLimitCallback(ClientData clientData);

/* NRE enabling */
static Tcl_NRPostProc	NRPostInvokeHidden;
static Tcl_ObjCmdProc	NRInterpCmd;
static Tcl_ObjCmdProc	NRChildCmd;


/*
 *----------------------------------------------------------------------
 *
 * TclSetPreInitScript --
 *
 *	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(
    const char *string)		/* Pointer to a script. */
{
    const char *prevString = tclPreInitScript;
    tclPreInitScript = string;
    return(prevString);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Init --
 *







|

|
>


|










|














|




|







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
static int		ChildTimeLimitCmd(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, int consumedObjc,
			    int 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(void *clientData,
			    Tcl_Interp *interp);
static void		DeleteScriptLimitCallback(void *clientData);
static void		MakeSafe(Tcl_Interp *interp);
static void		RunLimitHandlers(LimitHandler *handlerPtr,
			    Tcl_Interp *interp);
static void		TimeLimitCallback(void *clientData);

/* NRE enabling */
static Tcl_NRPostProc	NRPostInvokeHidden;
static Tcl_ObjCmdProc	NRInterpCmd;
static Tcl_ObjCmdProc	NRChildCmd;


/*
 *----------------------------------------------------------------------
 *
 * 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 *
Tcl_SetPreInitScript(
    const char *string)		/* Pointer to a script. */
{
    const char *prevString = tclPreInitScript;
    tclPreInitScript = string;
    return prevString;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Init --
 *
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
    char name[4];
} PkgName;

int
Tcl_Init(
    Tcl_Interp *interp)		/* Interpreter to initialize. */
{
    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) {
	    goto end;
	}
    }

    /*
     * In order to find init.tcl during initialization, the following script
     * is invoked by Tcl_Init(). It looks in several different directories:







|






|







329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
    char name[4];
} PkgName;

int
Tcl_Init(
    Tcl_Interp *interp)		/* Interpreter to initialize. */
{
    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, TCL_INDEX_NONE, 0) == 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
"	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"

"	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"







>





<







398
399
400
401
402
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
"	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 {\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"
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
"    set msg \"Can't 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);

end:
    *names = (*names)->nextPtr;
    return result;
}

/*







|







446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
"    set msg \"Can't 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", TCL_INDEX_NONE, 0);

end:
    *names = (*names)->nextPtr;
    return result;
}

/*
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
 *	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. */
{
    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 *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",







|















<







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_InterpObjCmd(
    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 *childInterp;

    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
	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
    };

    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) {
	/* Don't report the "slaves" option as possibility */
	Tcl_GetIndexFromObj(interp, objv[1], optionsNoSlaves,
		"option", 0, &index);
	return TCL_ERROR;
    }
    switch ((enum interpOptionEnum)index) {
    case OPT_ALIAS: {
	Tcl_Interp *parentInterp;

	if (objc < 4) {
	aliasArgs:
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "childPath childCmd ?parentPath parentCmd? ?arg ...?");







|












|







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
	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;

    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) {
	/* Don't report the "slaves" option as possibility */
	Tcl_GetIndexFromObj(interp, objv[1], optionsNoSlaves,
		"option", 0, &index);
	return TCL_ERROR;
    }
    switch (index) {
    case OPT_ALIAS: {
	Tcl_Interp *parentInterp;

	if (objc < 4) {
	aliasArgs:
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "childPath childCmd ?parentPath parentCmd? ?arg ...?");
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
	int i, flags;
	Tcl_Obj *resultObjPtr;
	static const char *const cancelOptions[] = {
	    "-unwind",	"--",	NULL
	};
	enum optionCancelEnum {
	    OPT_UNWIND,	OPT_LAST
	};

	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) {
		return TCL_ERROR;
	    }

	    switch ((enum optionCancelEnum) index) {
	    case OPT_UNWIND:
		/*
		 * The evaluation stack in the target interp is to be unwound.
		 */

		flags |= TCL_CANCEL_UNWIND;
		break;







|








|



|







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
	int i, flags;
	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, &idx) != TCL_OK) {
		return TCL_ERROR;
	    }

	    switch (idx) {
	    case OPT_UNWIND:
		/*
		 * The evaluation stack in the target interp is to be unwound.
		 */

		flags |= TCL_CANCEL_UNWIND;
		break;
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_Obj *childPtr;
	char buf[16 + TCL_INTEGER_SPACE];
	static const char *const createOptions[] = {
	    "-safe",	"--", NULL
	};
	enum option {
	    OPT_SAFE,	OPT_LAST
	};

	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) {
		    return TCL_ERROR;
		}
		if (index == OPT_SAFE) {
		    safe = 1;
		    continue;
		}
		i++;
		last = 1;
	    }
	    if (childPtr != NULL) {







|












|


|







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_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, &idx) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (idx == OPT_SAFE) {
		    safe = 1;
		    continue;
		}
		i++;
		last = 1;
	    }
	    if (childPtr != NULL) {
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
	     * 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) {
		    break;
		}
	    }
	    childPtr = Tcl_NewStringObj(buf, -1);
	}
	if (ChildCreate(interp, childPtr, safe) == NULL) {







|







829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
	     * for the interpreter does not collide with an existing command
	     * in the parent interpreter.
	     */

	    for (i = 0; ; i++) {
		Tcl_CmdInfo cmdInfo;

		snprintf(buf, sizeof(buf), "interp%d", i);
		if (Tcl_GetCommandInfo(interp, buf, &cmdInfo) == 0) {
		    break;
		}
	    }
	    childPtr = Tcl_NewStringObj(buf, -1);
	}
	if (ChildCreate(interp, childPtr, safe) == NULL) {
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
	    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);
		return TCL_ERROR;
	    }
	    iiPtr = (InterpInfo *) ((Interp *) childInterp)->interpInfo;
	    Tcl_DeleteCommandFromToken(iiPtr->child.parentInterp,
		    iiPtr->child.interpCmd);
	}
	return TCL_OK;







|







871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
	    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", (char *)NULL);
		return TCL_ERROR;
	    }
	    iiPtr = (InterpInfo *) ((Interp *) childInterp)->interpInfo;
	    Tcl_DeleteCommandFromToken(iiPtr->child.parentInterp,
		    iiPtr->child.interpCmd);
	}
	return TCL_OK;
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
	int i;
	const char *namespaceName;
	static const char *const hiddenOptions[] = {
	    "-global",	"-namespace",	"--", NULL
	};
	enum hiddenOption {
	    OPT_GLOBAL,	OPT_NAMESPACE,	OPT_LAST
	};

	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) {
		return TCL_ERROR;
	    }
	    if (index == OPT_GLOBAL) {
		namespaceName = "::";
	    } else if (index == OPT_NAMESPACE) {
		if (++i == objc) { /* There must be more arguments. */
		    break;
		} else {
		    namespaceName = TclGetString(objv[i]);
		}
	    } else {
		i++;







|







|


|

|







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
	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, &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (idx == OPT_GLOBAL) {
		namespaceName = "::";
	    } 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
    }
    case OPT_LIMIT: {
	static const char *const limitTypes[] = {
	    "commands", "time", NULL
	};
	enum LimitTypes {
	    LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME
	};
	int 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) {
	case LIMIT_TYPE_COMMANDS:
	    return ChildCommandLimitCmd(interp, childInterp, 4, objc,objv);
	case LIMIT_TYPE_TIME:
	    return ChildTimeLimitCmd(interp, childInterp, 4, objc, objv);
	}
    }
    break;







<
|














|







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
    }
    case OPT_LIMIT: {
	static const char *const limitTypes[] = {
	    "commands", "time", NULL
	};
	enum LimitTypes {
	    LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME

	} 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 (limitType) {
	case LIMIT_TYPE_COMMANDS:
	    return ChildCommandLimitCmd(interp, childInterp, 4, objc,objv);
	case LIMIT_TYPE_TIME:
	    return ChildTimeLimitCmd(interp, childInterp, 4, objc, objv);
	}
    }
    break;
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
	iiPtr = (InterpInfo *) ((Interp *) childInterp)->interpInfo;
	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);
	    return TCL_ERROR;
	}
	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);
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    }
    return TCL_OK;
}







|








|







1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
	iiPtr = (InterpInfo *) ((Interp *) childInterp)->interpInfo;
	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,
		    (char *)NULL);
	    return TCL_ERROR;
	}
	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", (char *)NULL);
	    return TCL_ERROR;
	}
	return TCL_OK;
    }
    }
    return TCL_OK;
}
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214

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? */
    const char *const *argv)	/* These are the additional args. */
{
    Tcl_Obj *childObjPtr, *targetObjPtr;
    Tcl_Obj **objv;
    int i;
    int result;

    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]);
    }







|




|







1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213

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. */
    Tcl_Size argc,			/* How many additional arguments? */
    const char *const *argv)	/* These are the additional args. */
{
    Tcl_Obj *childObjPtr, *targetObjPtr;
    Tcl_Obj **objv;
    Tcl_Size i;
    int result;

    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]);
    }
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264

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_Obj *const objv[])	/* Argument vector. */
{
    Tcl_Obj *childObjPtr, *targetObjPtr;
    int result;

    childObjPtr = Tcl_NewStringObj(childCmd, -1);
    Tcl_IncrRefCount(childObjPtr);







|







1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263

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. */
    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);
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
 *	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) {







|




















|







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
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */
#ifndef TCL_NO_DEPRECATED
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, (char *)NULL);
	return TCL_ERROR;
    }
    aliasPtr = (Alias *)Tcl_GetHashValue(hPtr);
    objc = aliasPtr->objc;
    objv = &aliasPtr->objPtr;

    if (targetInterpPtr != NULL) {
1331
1332
1333
1334
1335
1336
1337

1338
1339
1340
1341
1342
1343
1344
		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.







>







1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
		Tcl_Alloc(sizeof(const char *) * (objc - 1));
	for (i = 1; i < objc; i++) {
	    (*argvPtr)[i - 1] = TclGetString(objv[i]);
	}
    }
    return TCL_OK;
}
#endif /* TCL_NO_DEPRECATED */

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetAliasObj --
 *
 *	Object version: Gets information about an alias.
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
    int 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) {







|







1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
    int 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, (char *)NULL);
	return TCL_ERROR;
    }
    aliasPtr = (Alias *)Tcl_GetHashValue(hPtr);
    objc = aliasPtr->objc;
    objv = &aliasPtr->objPtr;

    if (targetInterpPtr != NULL) {
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
	}
	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);
	    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.







|







1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
	}
	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", (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.
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710

    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->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);
	return TCL_ERROR;
    }
    aliasPtr = (Alias *)Tcl_GetHashValue(hPtr);
    Tcl_DeleteCommandFromToken(childInterp, aliasPtr->childCmd);
    return TCL_OK;
}








|







1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710

    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->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), (char *)NULL);
	return TCL_ERROR;
    }
    aliasPtr = (Alias *)Tcl_GetHashValue(hPtr);
    Tcl_DeleteCommandFromToken(childInterp, aliasPtr->childCmd);
    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
 *	forwarded.
 *
 *----------------------------------------------------------------------
 */

static int
AliasNRCmd(
    ClientData 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;
    Tcl_Obj **prefv, **cmdv;
    Tcl_Obj *listPtr;
    List *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;


    listPtr = Tcl_NewListObj(cmdc, NULL);

    listRep = ListRepPtr(listPtr);
    listRep->elemCount = cmdc;
    cmdv = &listRep->elements;




    prefv = &aliasPtr->objPtr;
    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. */
    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;
    Tcl_Interp *targetInterp = aliasPtr->targetInterp;







|








|











>

>
|
|
|
>
>
|
>

|
|



















|







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
 *	forwarded.
 *
 *----------------------------------------------------------------------
 */

static int
AliasNRCmd(
    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;
    Tcl_Obj **prefv, **cmdv;
    Tcl_Obj *listPtr;
    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);
    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 *));

    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(
    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;
    Tcl_Interp *targetInterp = aliasPtr->targetInterp;
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
    }
    return result;
#undef ALIAS_CMDV_PREALLOC
}

int
TclLocalAliasObjCmd(
    ClientData 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;







|







1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
    }
    return result;
#undef ALIAS_CMDV_PREALLOC
}

int
TclLocalAliasObjCmd(
    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;
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
 *	interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
AliasObjCmdDeleteProc(
    ClientData clientData)	/* The alias record for this alias. */
{
    Alias *aliasPtr = (Alias *)clientData;
    Target *targetPtr;
    int i;
    Tcl_Obj **objv;

    Tcl_DecrRefCount(aliasPtr->token);







|







2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
 *	interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
AliasObjCmdDeleteProc(
    void *clientData)	/* The alias record for this alias. */
{
    Alias *aliasPtr = (Alias *)clientData;
    Target *targetPtr;
    int i;
    Tcl_Obj **objv;

    Tcl_DecrRefCount(aliasPtr->token);
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
    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_Interp *searchInterp;	/* Interim storage for interp. to find. */
    InterpInfo *parentInfoPtr;

    if (TclListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
	return NULL;
    }








|







2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
    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;
    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;
    }

2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
	    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);
    }
    return searchInterp;
}

/*
 *----------------------------------------------------------------------
 *







|







2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
	    break;
	}
    }
    if (searchInterp == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not find interpreter \"%s\"", TclGetString(pathPtr)));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "INTERP",
		TclGetString(pathPtr), (char *)NULL);
    }
    return searchInterp;
}

/*
 *----------------------------------------------------------------------
 *
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
ChildBgerror(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* Interp in which limit is set/queried. */
    int objc,			/* Set or Query. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    if (objc) {
	int 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);
	    return TCL_ERROR;
	}
	TclSetBgErrorHandler(childInterp, objv[0]);
    }
    Tcl_SetObjResult(interp, TclGetBgErrorHandler(childInterp));
    return TCL_OK;
}







|






|







2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
ChildBgerror(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* Interp in which limit is set/queried. */
    int objc,			/* Set or Query. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    if (objc) {
	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", (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
    int safe)			/* Should we make it "safe"? */
{
    Tcl_Interp *parentInterp, *childInterp;
    Child *childPtr;
    InterpInfo *parentInfoPtr;
    Tcl_HashEntry *hPtr;
    const char *path;
    int isNew, objc;

    Tcl_Obj **objv;

    if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
	return NULL;
    }
    if (objc < 2) {
	parentInterp = interp;
	path = TclGetString(pathPtr);
    } else {
	Tcl_Obj *objPtr;







|
>


|







2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
    int safe)			/* Should we make it "safe"? */
{
    Tcl_Interp *parentInterp, *childInterp;
    Child *childPtr;
    InterpInfo *parentInfoPtr;
    Tcl_HashEntry *hPtr;
    const char *path;
    int isNew;
    Tcl_Size objc;
    Tcl_Obj **objv;

    if (TclListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) {
	return NULL;
    }
    if (objc < 2) {
	parentInterp = interp;
	path = TclGetString(pathPtr);
    } else {
	Tcl_Obj *objPtr;
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
     * Inherit the recursion limit.
     */

    ((Interp *) childInterp)->maxNestingDepth =
	    ((Interp *) parentInterp)->maxNestingDepth;

    if (safe) {
	if (Tcl_MakeSafe(childInterp) == TCL_ERROR) {
	    goto error;
	}
    } else {
	if (Tcl_Init(childInterp) == TCL_ERROR) {
	    goto error;
	}

	/*
	 * This will create the "memory" command in child interpreters if we







|
<
<







2479
2480
2481
2482
2483
2484
2485
2486


2487
2488
2489
2490
2491
2492
2493
     * Inherit the recursion limit.
     */

    ((Interp *) childInterp)->maxNestingDepth =
	    ((Interp *) parentInterp)->maxNestingDepth;

    if (safe) {
	MakeSafe(childInterp);


    } 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
 *	See user documentation for details.
 *
 *----------------------------------------------------------------------
 */

int
TclChildObjCmd(
    ClientData 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. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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
    };

    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) {
    case OPT_ALIAS:
	if (objc > 2) {
	    if (objc == 3) {
		return AliasDescribe(interp, childInterp, objv[2]);
	    }
	    if (TclGetString(objv[3])[0] == '\0') {
		if (objc == 4) {







|









|





<











|














|







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
 *	See user documentation for details.
 *
 *----------------------------------------------------------------------
 */

int
TclChildObjCmd(
    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(
    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;

    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 (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) {
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
	int i;
	const char *namespaceName;
	static const char *const hiddenOptions[] = {
	    "-global",	"-namespace",	"--", NULL
	};
	enum hiddenOption {
	    OPT_GLOBAL,	OPT_NAMESPACE,	OPT_LAST
	};

	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) {
		return TCL_ERROR;
	    }
	    if (index == OPT_GLOBAL) {
		namespaceName = "::";
	    } else if (index == OPT_NAMESPACE) {
		if (++i == objc) { /* There must be more arguments. */
		    break;
		} else {
		    namespaceName = TclGetString(objv[i]);
		}
	    } else {
		i++;







|







|


|

|







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
	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 = 2; i < objc; i++) {
	    if (TclGetString(objv[i])[0] != '-') {
		break;
	    }
	    if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions, "option",
		    0, &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (idx == OPT_GLOBAL) {
		namespaceName = "::";
	    } else if (idx == OPT_NAMESPACE) {
		if (++i == objc) { /* There must be more arguments. */
		    break;
		} else {
		    namespaceName = TclGetString(objv[i]);
		}
	    } else {
		i++;
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
    }
    case OPT_LIMIT: {
	static const char *const limitTypes[] = {
	    "commands", "time", NULL
	};
	enum LimitTypes {
	    LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME
	};
	int 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) {
	case LIMIT_TYPE_COMMANDS:
	    return ChildCommandLimitCmd(interp, childInterp, 3, objc,objv);
	case LIMIT_TYPE_TIME:
	    return ChildTimeLimitCmd(interp, childInterp, 3, objc, objv);
	}
    }
    break;







<
|









|







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
    }
    case OPT_LIMIT: {
	static const char *const limitTypes[] = {
	    "commands", "time", NULL
	};
	enum LimitTypes {
	    LIMIT_TYPE_COMMANDS, LIMIT_TYPE_TIME

	} 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 (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
 *	the child interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
ChildObjCmdDeleteProc(
    ClientData clientData)	/* The ChildRecord for the command. */
{
    Child *childPtr;		/* Interim storage for Child record. */
    Tcl_Interp *childInterp = (Tcl_Interp *)clientData;
				/* And for a child interp. */

    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->child;








|







2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
 *	the child interpreter.
 *
 *----------------------------------------------------------------------
 */

static void
ChildObjCmdDeleteProc(
    void *clientData)	/* The ChildRecord for the command. */
{
    Child *childPtr;		/* Interim storage for Child record. */
    Tcl_Interp *childInterp = (Tcl_Interp *)clientData;
				/* And for a child interp. */

    childPtr = &((InterpInfo *) ((Interp *) childInterp)->interpInfo)->child;

2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
    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);
	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);







|







2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
    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",
		(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);
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
ChildRecursionLimit(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* Interp in which limit is set/queried. */
    int objc,			/* Set or Query. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    Interp *iPtr;
    int 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);
	    return TCL_ERROR;
	}
	if (TclGetIntFromObj(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);
	    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);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, objv[0]);
	return TCL_OK;
    } else {
	limit = Tcl_SetRecursionLimit(childInterp, 0);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(limit));







|






|


|






|







|







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
ChildRecursionLimit(
    Tcl_Interp *interp,		/* Interp for error return. */
    Tcl_Interp *childInterp,	/* Interp in which limit is set/queried. */
    int objc,			/* Set or Query. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    Interp *iPtr;
    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",
		    (char *)NULL);
	    return 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",
		    (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", (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));
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
    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);
	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;







|







3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
    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",
		(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;
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
    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);
	return TCL_ERROR;
    }

    Tcl_Preserve(childInterp);
    Tcl_AllowExceptions(childInterp);

    if (namespaceName == NULL) {







|







3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
    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",
		(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

    Tcl_Release(childInterp);
    return result;
}

static int
NRPostInvokeHidden(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Interp *childInterp = (Tcl_Interp *)data[0];
    NRE_callback *rootPtr = (NRE_callback *)data[1];

    if (interp != childInterp) {







|







3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193

    Tcl_Release(childInterp);
    return result;
}

static int
NRPostInvokeHidden(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Interp *childInterp = (Tcl_Interp *)data[0];
    NRE_callback *rootPtr = (NRE_callback *)data[1];

    if (interp != childInterp) {
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
				 * 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);
	return TCL_ERROR;
    }
    ((Interp *) childInterp)->flags &= ~SAFE_INTERP;
    return TCL_OK;
}

/*







|







3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
				 * 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",
		(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
    }
    return (iPtr->flags & SAFE_INTERP) ? 1 : 0;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_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(
    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;

    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);
    }

    iPtr->flags |= SAFE_INTERP;

    /*
     * Unsetting variables : (which should not have been set in the first
     * place, but...)







|















|
|

















|







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
    }
    return (iPtr->flags & SAFE_INTERP) ? 1 : 0;
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

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;

    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 {}}", 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

    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
     * 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);








|







3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335

    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 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
    if (chan != NULL) {
	Tcl_UnregisterChannel(interp, chan);
    }
    chan = Tcl_GetStdChannel(TCL_STDERR);
    if (chan != NULL) {
	Tcl_UnregisterChannel(interp, chan);
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LimitExceeded --
 *







<
<







3351
3352
3353
3354
3355
3356
3357


3358
3359
3360
3361
3362
3363
3364
    if (chan != NULL) {
	Tcl_UnregisterChannel(interp, chan);
    }
    chan = Tcl_GetStdChannel(TCL_STDERR);
    if (chan != NULL) {
	Tcl_UnregisterChannel(interp, chan);
    }


}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_LimitExceeded --
 *
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
	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_Release(interp);
	    return TCL_ERROR;
	}
	Tcl_Release(interp);
    }

    if ((iPtr->limit.active & TCL_LIMIT_TIME) &&







|







3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
	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", (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
	    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_Release(interp);
		return TCL_ERROR;
	    }
	    Tcl_Release(interp);
	}
    }








|







3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
	    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", (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
 */

void
Tcl_LimitAddHandler(
    Tcl_Interp *interp,
    int type,
    Tcl_LimitHandlerProc *handlerProc,
    ClientData 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;
    }

    /*
     * Allocate a handler record.
     */

    handlerPtr = (LimitHandler *)Tcl_Alloc(sizeof(LimitHandler));







|









|
|







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
 */

void
Tcl_LimitAddHandler(
    Tcl_Interp *interp,
    int type,
    Tcl_LimitHandlerProc *handlerProc,
    void *clientData,
    Tcl_LimitHandlerDeleteProc *deleteProc)
{
    Interp *iPtr = (Interp *) interp;
    LimitHandler *handlerPtr;

    /*
     * Convert everything into a real deletion callback.
     */

    if (deleteProc == TCL_DYNAMIC) {
	deleteProc = TclpFree;
    }

    /*
     * Allocate a handler record.
     */

    handlerPtr = (LimitHandler *)Tcl_Alloc(sizeof(LimitHandler));
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
 */

void
Tcl_LimitRemoveHandler(
    Tcl_Interp *interp,
    int type,
    Tcl_LimitHandlerProc *handlerProc,
    ClientData clientData)
{
    Interp *iPtr = (Interp *) interp;
    LimitHandler *handlerPtr;

    switch (type) {
    case TCL_LIMIT_COMMANDS:
	handlerPtr = iPtr->limit.cmdHandlers;







|







3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
 */

void
Tcl_LimitRemoveHandler(
    Tcl_Interp *interp,
    int type,
    Tcl_LimitHandlerProc *handlerProc,
    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
 *
 *----------------------------------------------------------------------
 */

void
Tcl_LimitSetCommands(
    Tcl_Interp *interp,
    int commandLimit)
{
    Interp *iPtr = (Interp *) interp;

    iPtr->limit.cmdCount = commandLimit;
    iPtr->limit.exceeded &= ~TCL_LIMIT_COMMANDS;
}








|







3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
 *
 *----------------------------------------------------------------------
 */

void
Tcl_LimitSetCommands(
    Tcl_Interp *interp,
    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
 *	commands. May make callbacks into other interpreters.
 *
 *----------------------------------------------------------------------
 */

static void
TimeLimitCallback(
    ClientData clientData)
{
    Tcl_Interp *interp = (Tcl_Interp *)clientData;
    Interp *iPtr = (Interp *)clientData;
    int code;

    Tcl_Preserve(interp);
    iPtr->limit.timeEvent = NULL;







|







4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
 *	commands. May make callbacks into other interpreters.
 *
 *----------------------------------------------------------------------
 */

static void
TimeLimitCallback(
    void *clientData)
{
    Tcl_Interp *interp = (Tcl_Interp *)clientData;
    Interp *iPtr = (Interp *)clientData;
    int code;

    Tcl_Preserve(interp);
    iPtr->limit.timeEvent = NULL;
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
 *	is removed.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteScriptLimitCallback(
    ClientData clientData)
{
    ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *)clientData;

    Tcl_DecrRefCount(limitCBPtr->scriptObj);
    if (limitCBPtr->entryPtr != NULL) {
	Tcl_DeleteHashEntry(limitCBPtr->entryPtr);
    }







|







4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
 *	is removed.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteScriptLimitCallback(
    void *clientData)
{
    ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *)clientData;

    Tcl_DecrRefCount(limitCBPtr->scriptObj);
    if (limitCBPtr->entryPtr != NULL) {
	Tcl_DeleteHashEntry(limitCBPtr->entryPtr);
    }
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
 *	errors.
 *
 *----------------------------------------------------------------------
 */

static void
CallScriptLimitCallback(
    ClientData clientData,
    TCL_UNUSED(Tcl_Interp *))
{
    ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *)clientData;
    int code;

    if (Tcl_InterpDeleted(limitCBPtr->interp)) {
	return;







|







4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
 *	errors.
 *
 *----------------------------------------------------------------------
 */

static void
CallScriptLimitCallback(
    void *clientData,
    TCL_UNUSED(Tcl_Interp *))
{
    ScriptLimitCallback *limitCBPtr = (ScriptLimitCallback *)clientData;
    int code;

    if (Tcl_InterpDeleted(limitCBPtr->interp)) {
	return;
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
 *	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
 *	another interpreter is either installed or removed.
 *
 *----------------------------------------------------------------------
 */

static void
SetScriptLimitCallback(







|







4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
 *	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 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
	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);
	if (hashPtr != NULL) {
	    Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback,
		    Tcl_GetHashValue(hashPtr));
	}
	return;
    }








|







4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
	Tcl_Panic("installing limit callback to the limited interpreter");
    }

    key.interp = targetInterp;
    key.type = type;

    if (scriptObj == NULL) {
	hashPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key);
	if (hashPtr != NULL) {
	    Tcl_LimitRemoveHandler(targetInterp, type, CallScriptLimitCallback,
		    Tcl_GetHashValue(hashPtr));
	}
	return;
    }

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
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const options[] = {
	"-command", "-granularity", "-value", NULL
    };
    enum Options {
	OPT_CMD, OPT_GRAN, OPT_VAL
    };
    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);
	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);
	if (hPtr != NULL) {
	    limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
	    if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
			limitCBPtr->scriptObj);
	    } else {
		goto putEmptyCommandInDict;







|

<














|









|







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
    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;

    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", (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, &key);
	if (hPtr != NULL) {
	    limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
	    if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
			limitCBPtr->scriptObj);
	    } else {
		goto putEmptyCommandInDict;
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
	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) {
	case OPT_CMD:
	    key.interp = childInterp;
	    key.type = TCL_LIMIT_COMMANDS;
	    hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
	    if (hPtr != NULL) {
		limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
		if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		    Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
		}
	    }
	    break;







|



|







4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
	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 (index) {
	case OPT_CMD:
	    key.interp = childInterp;
	    key.type = TCL_LIMIT_COMMANDS;
	    hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key);
	    if (hPtr != NULL) {
		limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
		if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		    Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
		}
	    }
	    break;
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
	}
	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_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) {
	    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);
		    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);
		    return TCL_ERROR;
		}
		break;
	    }
	}
	if (scriptObj != NULL) {
	    SetScriptLimitCallback(interp, TCL_LIMIT_COMMANDS, childInterp,







|








|













|
















|







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
	}
	return TCL_OK;
    } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
	Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?");
	return TCL_ERROR;
    } else {
	int i;
	Tcl_Size 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 (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", (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", (char *)NULL);
		    return TCL_ERROR;
		}
		break;
	    }
	}
	if (scriptObj != NULL) {
	    SetScriptLimitCallback(interp, TCL_LIMIT_COMMANDS, childInterp,
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
    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
    };
    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);
	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);
	if (hPtr != NULL) {
	    limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
	    if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
			limitCBPtr->scriptObj);
	    } else {
		goto putEmptyCommandInDict;







|

<














|









|







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
    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;

    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", (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, &key);
	if (hPtr != NULL) {
	    limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
	    if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		Tcl_DictObjPut(NULL, dictPtr, Tcl_NewStringObj(options[0], -1),
			limitCBPtr->scriptObj);
	    } else {
		goto putEmptyCommandInDict;
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
	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) {
	case OPT_CMD:
	    key.interp = childInterp;
	    key.type = TCL_LIMIT_TIME;
	    hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, (char *) &key);
	    if (hPtr != NULL) {
		limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
		if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		    Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
		}
	    }
	    break;







|



|







4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
	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 (index) {
	case OPT_CMD:
	    key.interp = childInterp;
	    key.type = TCL_LIMIT_TIME;
	    hPtr = Tcl_FindHashEntry(&iPtr->limit.callbacks, &key);
	    if (hPtr != NULL) {
		limitCBPtr = (ScriptLimitCallback *)Tcl_GetHashValue(hPtr);
		if (limitCBPtr != NULL && limitCBPtr->scriptObj != NULL) {
		    Tcl_SetObjResult(interp, limitCBPtr->scriptObj);
		}
	    }
	    break;
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
	}
	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_Obj *scriptObj = NULL, *granObj = NULL;
	Tcl_Obj *milliObj = NULL, *secObj = NULL;
	int gran = 0;
	Tcl_Time limitMoment;
	int 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) {
	    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);
		    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) {
		    return TCL_ERROR;
		}
		if (tmp < 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "milliseconds must be at least 0", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADVALUE", NULL);
		    return TCL_ERROR;
		}
		limitMoment.usec = ((long) 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) {
		    return TCL_ERROR;
		}
		if (tmp < 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "seconds must be at least 0", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADVALUE", NULL);
		    return TCL_ERROR;
		}
		limitMoment.sec = 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);
		    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);
		    return TCL_ERROR;
		}
	    }

	    if (milliLen > 0 || secLen > 0) {
		/*
		 * Force usec to be in range [0..1000000), possibly







|




|







|













|









|




|

|


|







|




|

|


|















|







|







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
	}
	return TCL_OK;
    } else if ((objc-consumedObjc) & 1 /* isOdd(objc-consumedObjc) */) {
	Tcl_WrongNumArgs(interp, consumedObjc, objv, "?-option value ...?");
	return TCL_ERROR;
    } else {
	int i;
	Tcl_Size scriptLen = 0, milliLen = 0, secLen = 0;
	Tcl_Obj *scriptObj = NULL, *granObj = NULL;
	Tcl_Obj *milliObj = NULL, *secObj = NULL;
	int gran = 0;
	Tcl_Time limitMoment;
	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 (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", (char *)NULL);
		    return TCL_ERROR;
		}
		break;
	    case OPT_MILLI:
		milliObj = objv[i+1];
		(void) TclGetStringFromObj(objv[i+1], &milliLen);
		if (milliLen == 0) {
		    break;
		}
		if (TclGetWideIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (tmp < 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "milliseconds must be non-negative", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADVALUE", (char *)NULL);
		    return TCL_ERROR;
		}
		limitMoment.usec = tmp*1000;
		break;
	    case OPT_SEC:
		secObj = objv[i+1];
		(void) TclGetStringFromObj(objv[i+1], &secLen);
		if (secLen == 0) {
		    break;
		}
		if (TclGetWideIntFromObj(interp, objv[i+1], &tmp) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (tmp < 0) {
		    Tcl_SetObjResult(interp, Tcl_NewStringObj(
			    "seconds must be non-negative", -1));
		    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "INTERP",
			    "BADVALUE", (char *)NULL);
		    return TCL_ERROR;
		}
		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", (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", (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
/*
 * 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
 *
 * 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"








|
|
|
|







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 © 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
    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
				 * single variables, and >0 used for array
				 * variables. */
    size_t 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;







|


|







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. */
    Tcl_Size bytes;		/* Size of C variable array. This is 0 when
				 * single variables, and >0 used for array
				 * variables. */
    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
#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,
			    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 = {
    "invalidReal",			/* name */
    NULL,				/* freeIntRepProc */
    NULL,				/* dupIntRepProc */
    NULL,				/* updateStringProc */
    NULL				/* setFromAnyProc */

};

/*
 * 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







|


















|
>







91
92
93
94
95
96
97
98
99
100
101
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(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 = {
    "invalidReal",			/* name */
    NULL,				/* freeIntRepProc */
    NULL,				/* dupIntRepProc */
    NULL,				/* updateStringProc */
    NULL,				/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

/*
 * 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
    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;







<
<
<
<
<
<
<
<







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 (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
    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_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;
    }








|















<
<
<
<
<
<
<
<







234
235
236
237
238
239
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. */
    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;








    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
	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. */







<
<
<
<
<
<
<
<







286
287
288
289
290
291
292








293
294
295
296
297
298
299
	break;
    case TCL_LINK_USHORT:
	linkPtr->bytes = size * sizeof(unsigned short);
	break;
    case TCL_LINK_UINT:
	linkPtr->bytes = size * sizeof(unsigned int);
	break;








    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. */
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
}

static inline int
GetWide(
    Tcl_Obj *objPtr,
    Tcl_WideInt *widePtr)
{
    if (Tcl_GetWideIntFromObj(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;
    ClientData clientData;
    int type, 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 (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;
	    }
#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;
	    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);

	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))
#endif /* ACCEPT_NAN */
	;
}

static inline int
IsSpecial(
    double a)
{
    return TclIsInfinite(a)
#ifdef ACCEPT_NAN
	|| TclIsNaN(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;


    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 (*endPtr == 'e' || *endPtr == 'E') {
	    ++endPtr;
	    if (*endPtr == '+' || *endPtr == '-') {
		++endPtr;
	    }
	    if (*endPtr == 0) {
		double doubleValue = 0.0;

		Tcl_GetDoubleFromObj(NULL, objPtr, &doubleValue);
		TclFreeIntRep(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].
 */

static int
GetInvalidIntFromObj(
    Tcl_Obj *objPtr,
    int *intPtr)
{
    size_t length;
    const char *str = TclGetStringFromObj(objPtr, &length);

    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].
 */

static int
GetInvalidDoubleFromObj(
    Tcl_Obj *objPtr,
    double *doublePtr)
{
    int intValue;

    if (TclHasIntRep(objPtr, &invalidRealType)) {
	goto gotdouble;
    }
    if (GetInvalidIntFromObj(objPtr, &intValue) == TCL_OK) {
	*doublePtr = (double) intValue;
	return TCL_OK;
    }
    if (SetInvalidRealFromAny(NULL, objPtr) == TCL_OK) {







|















|
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<












|

















|








|

|













|
|
>










|
|











|










|
|
|
|







|


|
|










|
|
|
|









|







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 (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)
{
    if (Tcl_GetWideUIntFromObj(NULL, objPtr, uwidePtr) != TCL_OK) {

	int intValue;














	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_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
	|| (isnan(a) && isnan(b))
#endif /* ACCEPT_NAN */
	;
}

static inline int
IsSpecial(
    double a)
{
    return isinf(a)
#ifdef ACCEPT_NAN
	|| isnan(a)
#endif /* ACCEPT_NAN */
	;
}

/*
 * Mark an object as holding a weird double.
 */

static int
SetInvalidRealFromAny(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *objPtr)
{
    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 (*endPtr == 'e' || *endPtr == 'E') {
	    ++endPtr;
	    if (*endPtr == '+' || *endPtr == '-') {
		++endPtr;
	    }
	    if (*endPtr == 0) {
		double doubleValue = 0.0;

		Tcl_GetDoubleFromObj(NULL, objPtr, &doubleValue);
		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"
 * (upperand lowercase). See bug [39f6304c2e].
 */

static int
GetInvalidIntFromObj(
    Tcl_Obj *objPtr,
    int *intPtr)
{
    Tcl_Size length;
    const char *str = TclGetStringFromObj(objPtr, &length);

    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 lowercase) and sequences like "1e-". See bug [39f6304c2e].
 */

static int
GetInvalidDoubleFromObj(
    Tcl_Obj *objPtr,
    double *doublePtr)
{
    int intValue;

    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
 *	modification.
 *
 *----------------------------------------------------------------------
 */

static char *
LinkTraceProc(
    ClientData 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;
    const char *value;
    char **pp;
    Tcl_Obj *valueObj;
    int valueInt;
    Tcl_WideInt valueWide;
    Tcl_WideUInt valueUWide;
    double valueDouble;
    int objc;
    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) {







|










|







|

<







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(
    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;
    Tcl_Size valueLength = 0;
    const char *value;
    char **pp;
    Tcl_Obj *valueObj;
    int valueInt;
    Tcl_WideInt valueWide;
    Tcl_WideUInt valueUWide;
    double valueDouble;
    Tcl_Size objc, i;
    Tcl_Obj **objv;


    /*
     * 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
		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;







<
<
<
<
<
<
<
<







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;








	    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
	}
	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
     * 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),







|







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 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
	} 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) {
	    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;







|
>
>
|







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 *) 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
    ((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) {
	    return (char *) "wrong dimension";
	}
    }

    switch (linkPtr->type) {
    case TCL_LINK_INT:
	if (linkPtr->flags & LINK_ALLOC_LAST) {
	    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";
		}







|
|







|







872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
    ((value) >= (lowerLimit) && (value) <= (upperLimit))

    /*
     * If we're working with an array of numbers, extract the Tcl list.
     */

    if (linkPtr->flags & LINK_ALLOC_LAST) {
	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++) {
		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";
		}
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
	}
	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)) {
		    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)) {
		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;
	}







|









|







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
	}
	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, (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, (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;
	}
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
	}
	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)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            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)) {
		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)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            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)) {
		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 *)







|









|













|









|








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
	}
	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, (int)USHRT_MAX)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *)
			"variable array must have unsigned short value";
		}
		linkPtr->lastValue.usPtr[i] = (unsigned short) valueInt;
	    }
	} else {
	    if (GetInt(valueObj, &valueInt)
		    || !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, (Tcl_WideInt)UINT_MAX)) {
		    Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
			    ObjValue(linkPtr), TCL_GLOBAL_ONLY);
	            return (char *)
			    "variable array must have unsigned int value";
		}
		linkPtr->lastValue.uiPtr[i] = (unsigned int) valueWide;
	    }
	} else {
	    if (GetWide(valueObj, &valueWide)
		    || !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;

















































    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 *)
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298

static Tcl_Obj *
ObjValue(
    Link *linkPtr)		/* Structure describing linked variable. */
{
    char *p;
    Tcl_Obj *resultObj, **objv;
    size_t 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++) {







|







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;
    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
	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]);
	    }
	    resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
	    Tcl_Free(objv);
	    return resultObj;
	}
	linkPtr->lastValue.d = LinkedVar(double);
	return Tcl_NewDoubleObj(linkPtr->lastValue.d);







|







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++) {
		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
	    }
	    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]);
	    }
	    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:
	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]);
	    }
	    resultObj = Tcl_NewListObj(linkPtr->numElems, objv);
	    Tcl_Free(objv);
	    return resultObj;
	}
	linkPtr->lastValue.uw = LinkedVar(Tcl_WideUInt);

	return Tcl_NewWideIntObj((Tcl_WideInt) linkPtr->lastValue.uw);



    case TCL_LINK_STRING:
	p = LinkedVar(char *);
	if (p == NULL) {
	    TclNewLiteralStringObj(resultObj, "NULL");
	    return resultObj;
	}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





|







|




<
|






>
|
>
>







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);




























    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++) {
		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: {
	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++) {

		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;
	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
/*
 * 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.
 *
 * 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>

/*






































































































 * Prototypes for 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);


/*
 * 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
 * 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 */

};

/* Macros to manipulate the List internal rep */












#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)




#ifndef TCL_MIN_ELEMENT_GROWTH


#define TCL_MIN_ELEMENT_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Obj *)






































































#endif





























































































/*
 *----------------------------------------------------------------------
 *
 * NewListIntRep --
 *
 *	Creates a 'List' structure with space for 'objc' elements.  'objc' must
 *	be > 0.  If 'objv' is not NULL, The list is initialized with first
 *	'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.
 *

 * Value

 *
 *	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.


 *
 * Effect
 *
 *	The refCount of each value in 'objv' is incremented as it is added
 *	to the list.
 *
 *----------------------------------------------------------------------
 */

static List *
NewListIntRep(
    int objc,
    Tcl_Obj *const objv[],
    int p)
{
    List *listRepPtr;

    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
     * 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",
		    LIST_MAX);
	}
	return NULL;
    }









    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",

		    LIST_SIZE(objc));
	}
	return NULL;
    }

    listRepPtr->canonicalFlag = 0;
    listRepPtr->refCount = 0;
    listRepPtr->maxElemCount = objc;



















    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]);
	}



    } else {
	listRepPtr->elemCount = 0;
    }
































    return listRepPtr;
}









/*
 *----------------------------------------------------------------------
 *




































 *  AttemptNewList --














 *




 *	Like NewListIntRep, but additionally sets an error message on failure.






















 *
 *----------------------------------------------------------------------
 */

static List *
AttemptNewList(
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])

{
    List *listRepPtr = NewListIntRep(objc, objv, 0);

    if (interp != NULL && listRepPtr == NULL) {
	if (objc > LIST_MAX) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "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)));
	}
	Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
    }








































































    return listRepPtr;




























}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewListObj --
 *

 *	Creates a new list object and adds values to it. When TCL_MEM_DEBUG is
 *	defined, 'Tcl_DbNewListObj' is called instead.


 *
 * Value


 *

 *	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.
 *
 * Effect
 *
 *	The refCount of each elements in 'objv' is incremented as it is added
 *	to the list.
 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG
#undef Tcl_NewListObj

Tcl_Obj *
Tcl_NewListObj(
    int 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_Obj *const objv[])	/* An array of pointers to Tcl objects. */
{
    List *listRepPtr;
    Tcl_Obj *listPtr;

    TclNewObj(listPtr);

    if (objc <= 0) {
	return listPtr;
    }

    /*
     * Create the internal rep.
     */

    listRepPtr = NewListIntRep(objc, objv, 1);

    /*
     * Now create the object.
     */

    TclInvalidateStringRep(listPtr);
    ListSetIntRep(listPtr, listRepPtr);
    return listPtr;
}
#endif /* if TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 *  Tcl_DbNewListObj --
 *



 *	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.
 *
 *	When TCL_MEM_DEBUG is not defined, 'Tcl_NewListObj' is called instead.











 *
 *----------------------------------------------------------------------
 */

#ifdef TCL_MEM_DEBUG

Tcl_Obj *
Tcl_DbNewListObj(
    int 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;

    TclDbNewObj(listPtr, file, line);

    if (objc <= 0) {
	return listPtr;
    }

    /*
     * Create the internal rep.
     */

    listRepPtr = NewListIntRep(objc, objv, 1);

    /*
     * Now create the object.
     */

    TclInvalidateStringRep(listPtr);
    ListSetIntRep(listPtr, listRepPtr);

    return listPtr;
}

#else /* if not TCL_MEM_DEBUG */

Tcl_Obj *
Tcl_DbNewListObj(
    int 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 */





































































































/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetListObj --
 *
 *	Like 'Tcl_NewListObj', but operates on an existing 'Tcl_Obj'instead of



 *	creating a new one.








 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetListObj(
    Tcl_Obj *objPtr,		/* Object whose internal rep to init. */
    int 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.

     */

    if (objc > 0) {


	listRepPtr = NewListIntRep(objc, objv, 1);
	ListSetIntRep(objPtr, listRepPtr);
    } else {


	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.
 *
 * 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
 *	in 'interp' if it is not NULL.
 *
 * Effect
 *
 *	'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
				 * to be returned. */
{
    Tcl_Obj *copyPtr;
    List *listRepPtr;

    ListGetIntRep(listPtr, listRepPtr);

    if (NULL == listRepPtr) {

	if (SetListFromAny(interp, listPtr) != TCL_OK) {
	    return NULL;
	}
    }

    TclNewObj(copyPtr);
    TclInvalidateStringRep(copyPtr);
    DupListInternalRep(listPtr, copyPtr);
    return copyPtr;






























































































































































































}

/*
 *----------------------------------------------------------------------
 *
 * TclListObjRange --
 *
 *	Makes a slice of a list value.
 *      *listPtr 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.


 *
 * Side effects:
 *	The possible conversion of the object referenced by listPtr
 *	to a list object.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclListObjRange(

    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 **elemPtrs;
    int listLen;
    size_t i, newLen;
    List *listRepPtr;


    TclListObjGetElements(NULL, listPtr, &listLen, &elemPtrs);

    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;
	TclNewObj(obj);
	return obj;
    }

    newLen = toIdx - fromIdx + 1;

    if (Tcl_IsShared(listPtr) ||

	    ((ListRepPtr(listPtr)->refCount > 1))) {


	return Tcl_NewListObj(newLen, &elemPtrs[fromIdx]);
    }

    /*
     * In-place is possible.
     */

    /*
     * Even if nothing below cause any changes, we still want the
     * string-canonizing effect of [lrange 0 end].
     */





    TclInvalidateStringRep(listPtr);

    /*
     * Delete elements that should not be included.

     */

    for (i = 0; i < fromIdx; i++) {
	TclDecrRefCount(elemPtrs[i]);
    }
    for (i = toIdx + 1; i < (size_t)listLen; i++) {
	TclDecrRefCount(elemPtrs[i]);
    }

    if (fromIdx > 0) {
	memmove(elemPtrs, &elemPtrs[fromIdx],

		(size_t) newLen * sizeof(Tcl_Obj*));
    }

    listRepPtr = ListRepPtr(listPtr);
    listRepPtr->elemCount = newLen;

    return listPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjGetElements --
 *
 *	Retreive the elements in a list 'Tcl_Obj'.
 *
 * 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'.



 *
 *	    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.
 *
 *	TCL_ERROR
 *
 *	    'listPtr' is not a valid list. An error message is left in the
 *	    interpreter's result if 'interp' is not NULL.
 *
 * Effect
 *

 *	'listPtr' is converted to a list object if it isn't one already.
 *
 *----------------------------------------------------------------------
 */


int
Tcl_ListObjGetElements(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *listPtr,	/* List object for which an element array is
				 * to be returned. */
    int *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;

    ListGetIntRep(listPtr, listRepPtr);

    if (listRepPtr == NULL) {
	int result;
	size_t length;

	(void) TclGetStringFromObj(listPtr, &length);
	if (length == 0) {
	    *objcPtr = 0;
	    *objvPtr = NULL;
	    return TCL_OK;
	}
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
	ListGetIntRep(listPtr, listRepPtr);
    }
    *objcPtr = listRepPtr->elemCount;
    *objvPtr = &listRepPtr->elements;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjAppendList --
 *
 *	Appends the elements of elemListPtr to those of listPtr.

 *
 * Value
 *
 *	TCL_OK
 *
 *	    Success.
 *
 *	TCL_ERROR
 *
 *	    'listPtr' or 'elemListPtr' are not valid lists.  An error
 *	    message is left in the interpreter's result if 'interp' is not NULL.
 *
 * Effect
 *
 *	The reference count of each element of 'elemListPtr' as it is added to
 *	'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
 *	'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. */
{
    int objc;
    Tcl_Obj **objv;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList");
    }

    /*
     * Pull the elements to append from elemListPtr.
     */

    if (TCL_OK != TclListObjGetElements(interp, elemListPtr, &objc, &objv)) {
	return TCL_ERROR;
    }

    /*
     * Insert the new elements starting after the lists's last element.
     * Delete zero existing elements.
     */



    return Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, objc, objv);




















































































































































}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjAppendElement --
 *





<
<
|





>

|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
|
|
|
>





|
<
<
<
<
<
<







|
>



>
>
>
>
>
>
>

>
>
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>

>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|

|
|
<
|
|

>
|
>

<
|
|
>
>

|
<
|
|



<
|
|
|

|

|
|
<
<
<



|
<
<

<
|
|
|
<




>
>
>
>
>
>
>
>
|
>
|
|
|
>





<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
|
<
<
<
<
<
|
>
>
>

|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
|
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



<
|
|

|
|
>

|

|

|
<
<

<
<
|

<

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
|
<
>
>

<
>
>

>
|
|
|
|

|
<
|
|









|









|


|
|

|


|


<
<
<
|
<
|
<
<
<

<
<
|






|

>
>
>
|
|
|
|

|
>
>
>
>
>
>
>
>
>
>
>








|






|
|

|


|


<
<
<
|
<
|
<
<
<

<
<
<
|






|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|
>
>
>
|
>
>
>
>
>
>
>
>



<



|


<
<




<
<
<
<
<
<
<



|
>



>
>
|
|

>
>









|
|
|

|
|
|
|
|
<

|
|
<







|


|
<

|
>
|
>
|




|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|




>
>










>
|
|
|

<
|
<
|

>
|
|
<
<

<
<
|
<
|
<
<
|
|
<

|
>
|
>
>
|
|
|
|
|
<
|
<
<
<
<
>
|
>
>
>
|
|
<
<
>
|

<
|
<
<
|
<
|
<
<
>
|
<
|
<
<
|
|







|
|
<

<
|
>
|
|
>
>
>

|
|
|
|
|
|

<
<
<
<
<
|
<
>
|




>



|

|




|

|
|
<
<
<
|
|
<
<
<
|
|
<
<
<
<
<
<
|
<








|
>

|
<
|
<
<
<
|
<
<
|

|
<
|
<
>
|
|
|
<



<



|
|

|


|



<
<
<
<
|








>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150






151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
/*
 * tclListObj.c --
 *
 *	This file contains functions that implement the Tcl list object type.
 *


 * 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 "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 non-inline static functions defined later in this file:
 */
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 ListRep defined in tcl.h.






 */

const Tcl_ObjType tclListType = {
    "list",			/* name */
    FreeListInternalRep,	/* freeIntRepProc */
    DupListInternalRep,		/* dupIntRepProc */
    UpdateStringOfList,		/* updateStringProc */
    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))

/* 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", (void *)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", (void *)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;

    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__);
}

/*
 *----------------------------------------------------------------------
 *
 * ListStoreNew --
 *
 *	Allocates a new ListStore with space for at least objc elements. objc
 *	must be > 0.  If objv!=NULL, initializes with the first objc values

 *	in that array.  If objv==NULL, initalize 0 elements, with space
 *	to add objc more.
 *
 *      Normally the function allocates the exact space requested unless
 *      the flags arguments has any LISTREP_SPACE_*
 *      bits set. See the comments for those #defines.
 *

 * 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.
 *
 * Side effects:

 *	The ref counts of the elements in objv are incremented on success
 *	since the returned ListStore references them.
 *
 *----------------------------------------------------------------------
 */

static ListStore *
ListStoreNew(
    Tcl_Size objc,
    Tcl_Obj *const objv[],
    int flags)
{
    ListStore *storePtr;
    Tcl_Size capacity;




    /*
     * First check to see if we'd overflow and try to allocate an object
     * larger than our memory allocator allows.


     */

    if (objc > LIST_MAX) {
	if (flags & LISTREP_PANIC_ON_FAIL) {
	    Tcl_Panic("max length of a Tcl list exceeded");

	}
	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;
	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;
    }


    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) {
	storePtr->numUsed = objc;
	ObjArrayCopy(&storePtr->slots[storePtr->firstUsed], objc, objv);
    } else {
	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 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;

    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 int
ListRepInitAttempt(
    Tcl_Interp *interp,
    Tcl_Size objc,
    Tcl_Obj *const objv[],
    ListRep *repPtr)
{
    int result = ListRepInit(objc, objv, 0, repPtr);

    if (result != TCL_OK && interp != NULL) {
	if (objc > LIST_MAX) {
	    ListLimitExceededError(interp);


	} else {


	    MemoryAllocationError(interp, LIST_SIZE(objc));
	}

    }
    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;
    }

    /* 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
 *	TCL_MEM_DEBUG is not defined. It creates a new list object from an

 *	(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.
 *

 *	When TCL_MEM_DEBUG is defined, this function just returns the result
 *	of calling the debugging version Tcl_DbNewListObj.
 *
 * 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 resulting 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
#undef Tcl_NewListObj

Tcl_Obj *
Tcl_NewListObj(
    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(
    Tcl_Size objc,		/* Count of objects referenced by objv. */
    Tcl_Obj *const objv[])	/* An array of pointers to Tcl objects. */
{
    ListRep listRep;
    Tcl_Obj *listObj;

    TclNewObj(listObj);

    if (objc <= 0) {
	return listObj;
    }




    ListRepInit(objc, objv, LISTREP_PANIC_ON_FAIL, &listRep);

    ListObjReplaceRepAndInvalidate(listObj, &listRep);






    return listObj;
}
#endif /* if TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	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 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(
    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 *listObj;
    ListRep listRep;

    TclDbNewObj(listObj, file, line);

    if (objc <= 0) {
	return listObj;
    }




    ListRepInit(objc, objv, LISTREP_PANIC_ON_FAIL, &listRep);

    ListObjReplaceRepAndInvalidate(listObj, &listRep);







    return listObj;
}

#else /* if not TCL_MEM_DEBUG */

Tcl_Obj *
Tcl_DbNewListObj(
    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 --
 *
 *	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. */
    Tcl_Size objc,		/* Count of objects referenced by objv. */
    Tcl_Obj *const objv[])	/* An array of pointers to Tcl objects. */
{


    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetListObj");
    }








    /*
     * 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. NOTE ListRepInit must
     * not be called with objc == 0!
     */

    if (objc > 0) {
	ListRep listRep;
	/* TODO - perhaps ask for extra space? */
	ListRepInit(objc, objv, LISTREP_PANIC_ON_FAIL, &listRep);
	ListObjReplaceRepAndInvalidate(objPtr, &listRep);
    } else {
	TclFreeInternalRep(objPtr);
	TclInvalidateStringRep(objPtr);
	Tcl_InitStringRep(objPtr, NULL, 0);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclListObjCopy --
 *
 *	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.
 *
 * 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.

 *
 * Side effects:
 *	None.

 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclListObjCopy(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *listObj)		/* List object for which an element array is
				 * to be returned. */
{
    Tcl_Obj *copyObj;


    if (!TclHasInternalRep(listObj, &tclListType)) {
	if (TclObjTypeHasProc(listObj, lengthProc)) {
	    return Tcl_DuplicateObj(listObj);
	}
	if (SetListFromAny(interp, listObj) != TCL_OK) {
	    return NULL;
	}
    }

    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.
 *      *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 *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. */
{

    ListRep listRep;

    ListRep resultRep;

    int isShared;
    if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
	return NULL;


    }




    isShared = Tcl_IsShared(listObj);



    ListRepRange(&listRep, rangeStart, rangeEnd, isShared, &resultRep);


    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;
}

/*
 *----------------------------------------------------------------------

 *




 * TclListObjGetElement --
 *
 *	Returns a single element from the array of the elements in a list
 *	object, without doing doing any bounds checking.  Caller must ensure
 *	that ObjPtr of of type 'tclListType' and that  index is valid for the
 *	list.
 *


 *----------------------------------------------------------------------
 */


Tcl_Obj *


TclListObjGetElement(

    Tcl_Obj *objPtr,		/* List object for which an element array is


				 * to be returned. */
    Tcl_Size index

)


{
    return ListObjStorePtr(objPtr)->slots[ListObjStart(objPtr) + index];
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjGetElements --
 *
 *	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 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 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:

 *	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 *objPtr,		/* List 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. */
{
    ListRep listRep;

    if (TclObjTypeHasProc(objPtr, getElementsProc)) {
	return TclObjTypeGetElements(interp, objPtr, objcPtr, objvPtr);



    }
    if (TclListObjGetRep(interp, objPtr, &listRep) != TCL_OK) {



    	return TCL_ERROR;
    }






    ListRepElements(&listRep, *objcPtr, *objvPtr);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjAppendList --
 *
 *	This function appends the elements in the list fromObj
 *	to toObj. toObj must not be shared else the function will panic.
 *
 * Results:

 *	The return value is normally TCL_OK. If fromObj or toObj do not



 *	refer to list values, TCL_ERROR is returned and an error message is


 *	left in the interpreter's result if interp is not NULL.
 *
 * Side effects:

 *	The reference counts of the elements in fromObj are incremented

 *	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.

 *
 *----------------------------------------------------------------------
 */

int
Tcl_ListObjAppendList(
    Tcl_Interp *interp,		/* Used to report errors if not NULL. */
    Tcl_Obj *toObj,		/* List object to append elements to. */
    Tcl_Obj *fromObj)		/* List obj with elements to append. */
{
    Tcl_Size objc;
    Tcl_Obj **objv;

    if (Tcl_IsShared(toObj)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList");
    }





    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);
}

/*
 *------------------------------------------------------------------------
 *
 * 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) {
	/* 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
 *	    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
 *	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. */
{
    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
	 */

	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;
	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.
	     */

	    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 --
 *







|





<



|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
 *	    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 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 *toObj,		/* List object to append elemObj to. */
    Tcl_Obj *elemObj)		/* Object to append to toObj's list. */
{








































    /*


     * TODO - compare perf with 8.6 to see if worth optimizing single


















































     * element case








     */









    return TclListObjAppendElements(interp, toObj, 1, &elemObj);



























}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjIndex --
 *
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
 *	    '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
 *
 * 	    'listPtr' is not a valid list. An an error message is left in the
 * 	    interpreter's result if 'interp' is not NULL.
 *
 *  Effect
 *
 * 	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 **objPtrPtr)	/* The resulting Tcl_Obj* is stored here. */
{
    List *listRepPtr;

    ListGetIntRep(listPtr, listRepPtr);
    if (listRepPtr == NULL) {
	int result;
	size_t length;

	(void) TclGetStringFromObj(listPtr, &length);

	if (length == 0) {
	    *objPtrPtr = NULL;
	    return TCL_OK;
	}
	result = SetListFromAny(interp, listPtr);

	if (result != TCL_OK) {
	    return result;
	}
	ListGetIntRep(listPtr, listRepPtr);
    }



    if ((index < 0) || (index >= listRepPtr->elemCount)) {
	*objPtrPtr = NULL;
    } else {
	*objPtrPtr = (&listRepPtr->elements)[index];
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjLength --
 *
 * 	Retrieve the number of elements in a list.


 *
 * Value
 *
 *	TCL_OK
 *
 *	    A count of list elements is stored at the address provided by


 *	    'intPtr'. If 'listPtr' is not already of type 'tclListPtr', it is
 *	    converted.
 *
 *	TCL_ERROR
 *
 *	    'listPtr' is not a valid list.  An error message will be left in
 *	    the interpreter's result if 'interp' is not NULL.
 *
 *----------------------------------------------------------------------
 */


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. */
{
    List *listRepPtr;


    ListGetIntRep(listPtr, listRepPtr);
    if (listRepPtr == NULL) {
	int result;
	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);

    }





    *intPtr = listRepPtr->elemCount;

    return TCL_OK;

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjReplace --
 *
 *	Replace values in a list.



 *
 *	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 'count' is zero or negative no elements are deleted, and any new
 *	elements are inserted at the beginning of the list.
 *
 * 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.

 *


 *	TCL_ERROR
 *
 *	    'listPtr' is not a valid list.   An error message is left in the
 *	    interpreter's result if 'interp' is not NULL.
 *
 * Effect
 *
 *	If 'listPtr' is not of type 'tclListType', it is converted if possible.
 *
 *	The 'refCount' of each element appended to the list is incremented.
 *	Similarly, the 'refCount' for each replaced element is decremented.
 *

 *	If 'listPtr' is modified, any previous string representation is
 *	invalidated.
 *
 *----------------------------------------------------------------------
 */

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
				 * insert. */
{
    List *listRepPtr;







    Tcl_Obj **elemPtrs;
    int needGrow, numElems, numRequired, numAfterLast, start, i, j, isShared;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace");
    }

    ListGetIntRep(listPtr, listRepPtr);
    if (listRepPtr == NULL) {
	size_t length;

	(void) TclGetStringFromObj(listPtr, &length);
	if (length == 0) {
	    if (objc == 0) {
		return TCL_OK;

	    }
	    Tcl_SetListObj(listPtr, objc, NULL);
	} else {
	    int result = SetListFromAny(interp, listPtr);

	    if (result != TCL_OK) {

		return result;
	    }
	}
	ListGetIntRep(listPtr, listRepPtr);
    }

    /*
     * 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.
     */

    elemPtrs = &listRepPtr->elements;
    numElems = listRepPtr->elemCount;

    if (first < 0) {
	first = 0;
    }
    if (first >= numElems) {
	first = numElems;	/* 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 (objc > LIST_MAX - (numElems - count)) {
	if (interp != NULL) {

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "max length of a Tcl list (%d elements) exceeded",
		    LIST_MAX));
	}





	return TCL_ERROR;



    }
    isShared = (listRepPtr->refCount > 1);
    numRequired = numElems - count + objc; /* Known <= LIST_MAX */
    needGrow = numRequired > listRepPtr->maxElemCount;

    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));
	}
	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;

	    ListResetIntRep(listPtr, listRepPtr);
	    elemPtrs = &listRepPtr->elements;

	    listRepPtr->maxElemCount = attempt;
	    needGrow = numRequired > listRepPtr->maxElemCount;
	}
    }
    if (!needGrow && !isShared) {
	int shift;














	/*
	 * 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];



	    TclDecrRefCount(victimPtr);
	}







	/*
	 * Shift the elements after the last one removed to their new

	 * locations.






	 */








	start = first + count;
	numAfterLast = numElems - start;
	shift = objc - count;	/* numNewElems - numDeleted */
	if ((numAfterLast > 0) && (shift != 0)) {


	    Tcl_Obj **src = elemPtrs + start;





	    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;
	} else {
	    newMax = listRepPtr->maxElemCount;

	}





	listRepPtr = AttemptNewList(NULL, newMax, NULL);

	if (listRepPtr == NULL) {
	    unsigned int limit = LIST_MAX - numRequired;
	    unsigned int extra = numRequired - numElems
		    + TCL_MIN_ELEMENT_GROWTH;

	    int growth = (int) ((extra > limit) ? limit : extra);










	    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]);


		    }
		    return TCL_ERROR;







		}



	    }
	}









	ListResetIntRep(listPtr, listRepPtr);
	listRepPtr->refCount++;


	elemPtrs = &listRepPtr->elements;



	if (isShared) {




	    /*
	     * The old struct will remain in place; need new refCounts for the
	     * new List struct references. Copy over only the surviving

	     * elements.
	     */











	    for (i=0; i < first; i++) {
		elemPtrs[i] = oldPtrs[i];
		Tcl_IncrRefCount(elemPtrs[i]);

	    }
	    for (i = first + count, j = first + objc;
		    j < numRequired; i++, j++) {




		elemPtrs[j] = oldPtrs[i];

		Tcl_IncrRefCount(elemPtrs[j]);


	    }






	    oldListRepPtr->refCount--;
	} else {
	    /*

	     * The old struct will be removed; use its inherited refCounts.



	     */


	    if (first > 0) {
		memcpy(elemPtrs, oldPtrs, first * sizeof(Tcl_Obj *));



	    }







	    /*
	     * "Delete" count elements starting at first.
	     */


	    for (j = first;  j < first + count;  j++) {
		Tcl_Obj *victimPtr = oldPtrs[j];

		TclDecrRefCount(victimPtr);

	    }



	    /*
	     * Copy the elements after the last one removed, shifted to their
	     * new locations.

	     */





	    start = first + count;






	    numAfterLast = numElems - start;

	    if (numAfterLast > 0) {

		memcpy(elemPtrs + first + objc, oldPtrs + start,
			(size_t) numAfterLast * sizeof(Tcl_Obj *));

	    }








	    Tcl_Free(oldListRepPtr);
	}
    }










    /*
     * Insert the new elements into elemPtrs before "first".
     */





    for (i=0,j=first ; i<objc ; i++,j++) {
	elemPtrs[j] = objv[i];





    }







    /*
     * Update the count of elements.
     */








    listRepPtr->elemCount = numRequired;

    /*
     * Invalidate and free any old representations that may not agree

     * with the revised list's internal representation.
     */

    listRepPtr->refCount++;






    TclFreeIntRep(listPtr);

    ListSetIntRep(listPtr, listRepPtr);



    listRepPtr->refCount--;


    TclInvalidateStringRep(listPtr);


    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclLindexList --
 *
 *	Implements 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.
 *
 * Value
 *
 *	A pointer to the specified element, with its 'refCount' incremented, or
 *	NULL if an error occurred.
 *
 * Notes





 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclLindexList(
    Tcl_Interp *interp,		/* Tcl interpreter. */
    Tcl_Obj *listPtr,		/* List being unpacked. */
    Tcl_Obj *argPtr)		/* Index or index list. */
{

    size_t index;			/* Index into the list. */
    Tcl_Obj *indexListCopy;
    List *listRepPtr;


    /*
     * 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; see TIP#22 and TIP#33 for the details.
     */

    ListGetIntRep(argPtr, listRepPtr);
    if ((listRepPtr == NULL)
	    && TclGetIntForIndexM(NULL , argPtr, (size_t)WIDE_MAX - 1, &index) == TCL_OK) {
	/*
	 * argPtr designates a single index.
	 */

	return TclLindexFlat(interp, listPtr, 1, &argPtr);
    }

    /*
     * 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);
    if (indexListCopy == NULL) {
	/*
	 * argPtr designates something that is neither an index nor a
	 * well-formed list. Report the error via TclLindexFlat.

	 */

	return TclLindexFlat(interp, listPtr, 1, &argPtr);
    }

    ListGetIntRep(indexListCopy, listRepPtr);

    assert(listRepPtr != NULL);

    listPtr = TclLindexFlat(interp, listPtr, listRepPtr->elemCount,
		&listRepPtr->elements);
    Tcl_DecrRefCount(indexListCopy);
    return listPtr;
}

/*
 *----------------------------------------------------------------------
 *
 *  TclLindexFlat --
 *
 * 	The core of the 'lindex' command, with all index
 * 	arguments presented as a flat list.
 *
 *  Value



 *
 *	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:
 *




 * 		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 *const indexArray[])/* Array of pointers to Tcl objects that
				 * represent the indices in the list. */
{
    int i;





    Tcl_IncrRefCount(listPtr);

    for (i=0 ; i<indexCount && listPtr ; i++) {

	size_t index;
	int listLen = 0;
	Tcl_Obj **elemPtrs = NULL, *sublistCopy;


	/*
	 * 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) {
	    /*
	     * The sublist is not a list at all => error.
	     */







	    break;
	}
	TclListObjGetElements(NULL, sublistCopy, &listLen, &elemPtrs);

	if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1,
		&index) == TCL_OK) {
	    if (index >= (size_t)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);
			return NULL;
		    }
		}

		TclNewObj(listPtr);

	    } else {

		/*
		 * Extract the pointer to the appropriate element.

		 */







		listPtr = elemPtrs[index];
	    }






	    Tcl_IncrRefCount(listPtr);



	}

	Tcl_DecrRefCount(sublistCopy);

    }

    return listPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclLsetList --
 *
 *	The core of [lset] 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'.
 *
 * Value

 *
 *	The new list, with the 'refCount' of 'valuPtr' incremented, or NULL if

 *	there was an error.




 *
 *----------------------------------------------------------------------
 */

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'. */
{
    int 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 *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 (listRepPtr == NULL
	    && TclGetIntForIndexM(NULL, indexArgPtr, (size_t)WIDE_MAX - 1, &index) == TCL_OK) {
	/*









	 * indexArgPtr designates a single index.
	 */

	return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr);

    }


    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.
	 */

	return TclLsetFlat(interp, listPtr, 1, &indexArgPtr, valuePtr);
    }
    TclListObjGetElements(NULL, indexArgPtr, &indexCount, &indices);









    /*
     * Let TclLsetFlat handle the actual lset'ting.
     */

    retValuePtr = TclLsetFlat(interp, listPtr, indexCount, indices, valuePtr);

    Tcl_DecrRefCount(indexListCopy);





    return retValuePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclLsetFlat --
 *
 *	Core engine of the 'lset' command.
 *      It also handles 'lpop' when given a NULL value.
 *
 * Value
 *

 *	The resulting list
 *
 *	    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
 *	    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
 *	    exactly this.)
 *
 *	NULL
 *
 *	    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.
 *
 *
 * Effect
 *
 *	On entry, the reference count of 'listPtr' does not reflect any
 *	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.


 *
 *	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 *const indexArray[],
				/* Index args. */
    Tcl_Obj *valuePtr)		/* Value arg to 'lset' or NULL to 'lpop'. */
{
    size_t index;
    int result, len;
    Tcl_Obj *subListPtr, *retValuePtr, *chainPtr;
    Tcl_ObjIntRep *irPtr;



    /*
     * 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.
     */

    if (indexCount == 0) {
	if (valuePtr != NULL) {
	    Tcl_IncrRefCount(valuePtr);
	}
	return valuePtr;
    }

    /*
     * 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
     * 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
     * all elements to be unchanged.
     */

    subListPtr = Tcl_IsShared(listPtr) ? Tcl_DuplicateObj(listPtr) : listPtr;

    /*
     * Anchor the linked list of Tcl_Obj's whose string reps must be
     * invalidated if the operation succeeds.
     */

    retValuePtr = subListPtr;
    chainPtr = NULL;
    result = TCL_OK;








    /*
     * Loop through all the index arguments, and for each one dive into the
     * appropriate sublist.
     */

    do {
	int elemCount;
	Tcl_Obj *parentList, **elemPtrs;

	/*
	 * Check for the possible error conditions...
	 */

	if (TclListObjGetElements(interp, subListPtr, &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)  {
	    /* ...the index we're trying to use isn't an index at all. */
	    result = TCL_ERROR;
	    indexArray++;
	    break;
	}
	indexArray++;









	if (index > (size_t)elemCount
		|| (valuePtr == NULL && index >= (size_t)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"
			"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.
	 */

	if (--indexCount) {
	    parentList = subListPtr;
	    if (index == (size_t)elemCount) {
		TclNewObj(subListPtr);
	    } else {
		subListPtr = elemPtrs[index];
	    }
	    if (Tcl_IsShared(subListPtr)) {
		subListPtr = Tcl_DuplicateObj(subListPtr);
	    }

	    /*
	     * 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.
	     */

	    if (index == (size_t)elemCount) {
		Tcl_ListObjAppendElement(NULL, parentList, subListPtr);
	    } else {
		TclListObjSetElement(NULL, parentList, index, subListPtr);
	    }
	    if (Tcl_IsShared(subListPtr)) {
		subListPtr = Tcl_DuplicateObj(subListPtr);
		TclListObjSetElement(NULL, parentList, index, subListPtr);
	    }

	    /*
	     * 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.
	     */

	    irPtr = TclFetchIntRep(parentList, &tclListType);
	    irPtr->twoPtrValue.ptr2 = chainPtr;
	    chainPtr = parentList;

	}
    } 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.
     */

    while (chainPtr) {
	Tcl_Obj *objPtr = chainPtr;
	List *listRepPtr;

	/*
	 * Clear away our intrep surgery mess.
	 */

	irPtr = TclFetchIntRep(objPtr, &tclListType);
	listRepPtr = (List *)irPtr->twoPtrValue.ptr1;
	chainPtr = (Tcl_Obj *)irPtr->twoPtrValue.ptr2;

	if (result == TCL_OK) {

	    /*
	     * We're going to store valuePtr, so spoil string reps of all
	     * containing lists.






	     */




	    listRepPtr->refCount++;
	    TclFreeIntRep(objPtr);
	    ListSetIntRep(objPtr, listRepPtr);
	    listRepPtr->refCount--;

	    TclInvalidateStringRep(objPtr);
	} else {
	    irPtr->twoPtrValue.ptr2 = NULL;
	}



    }

    if (result != TCL_OK) {
	/*
	 * Error return; message is already in interp. Clean up any excess
	 * memory.
	 */

	if (retValuePtr != listPtr) {
	    Tcl_DecrRefCount(retValuePtr);
	}
	return NULL;
    }

    /*
     * Store valuePtr 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);
    } else {

	TclListObjSetElement(NULL, subListPtr, index, valuePtr);
	TclInvalidateStringRep(subListPtr);
    }
    Tcl_IncrRefCount(retValuePtr);
    return retValuePtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclListObjSetElement --
 *
 *	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
 *
 * 	TCL_OK
 *
 *	    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.
 *

 *	TCL_ERROR

 *

 *	    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
 *	    interpreter result.

 *
 * 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
				 * stored. */
    int index,			/* Index of element to store. */
    Tcl_Obj *valuePtr)		/* Tcl object to store in the designated list
				 * element. */
{



    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.
     */

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "TclListObjSetElement");
    }

    ListGetIntRep(listPtr, listRepPtr);
    if (listRepPtr == NULL) {
	int result;
	size_t length;

	(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;
	}
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
	ListGetIntRep(listPtr, listRepPtr);
    }

    elemCount = listRepPtr->elemCount;

    /*
     * Ensure that the index is in bounds.
     */

    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",
		    "OUTOFRANGE", NULL);
	}
	return TCL_ERROR;
    }

    /*
     * If the internal rep is shared, replace it with an unshared copy.

     */



    if (listRepPtr->refCount > 1) {
	Tcl_Obj **dst, **src = &listRepPtr->elements;
	List *newPtr = AttemptNewList(NULL, listRepPtr->maxElemCount, NULL);

	if (newPtr == NULL) {
	    newPtr = AttemptNewList(interp, elemCount, NULL);
	    if (newPtr == NULL) {
		return TCL_ERROR;
	    }
	}
	newPtr->refCount++;
	newPtr->elemCount = elemCount;
	newPtr->canonicalFlag = listRepPtr->canonicalFlag;

	dst = &newPtr->elements;
	while (elemCount--) {
	    *dst = *src++;
	    Tcl_IncrRefCount(*dst++);
	}

	listRepPtr->refCount--;

	listRepPtr = newPtr;
	ListResetIntRep(listPtr, listRepPtr);
    }
    elemPtrs = &listRepPtr->elements;

    /*
     * Add a reference to the new list element.
     */

    Tcl_IncrRefCount(valuePtr);

    /*
     * Remove a reference from the old list element.

     */

    Tcl_DecrRefCount(elemPtrs[index]);

    /*
     * Stash the new object in the list.
     */

    elemPtrs[index] = valuePtr;

    /*
     * Invalidate outdated intreps.
     */

    ListGetIntRep(listPtr, listRepPtr);
    listRepPtr->refCount++;
    TclFreeIntRep(listPtr);
    ListSetIntRep(listPtr, listRepPtr);
    listRepPtr->refCount--;

    TclInvalidateStringRep(listPtr);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeListInternalRep --
 *
 *	Deallocate the storage associated with the internal representation of a
 *	a list object.
 *
 * Effect

 *

 *	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. */
{
    List *listRepPtr;

    ListGetIntRep(listPtr, listRepPtr);
    assert(listRepPtr != NULL);

    if (listRepPtr->refCount-- <= 1) {
	Tcl_Obj **elemPtrs = &listRepPtr->elements;
	int i, numElems = listRepPtr->elemCount;

	for (i = 0;  i < numElems;  i++) {
	    Tcl_DecrRefCount(elemPtrs[i]);
	}
	Tcl_Free(listRepPtr);

    }
}

/*
 *----------------------------------------------------------------------
 *
 * DupListInternalRep --
 *
 *	Initialize the internal representation of a list 'Tcl_Obj' to share the
 *	internal representation of an existing list object.
 *
 * Effect

 *

 *	The 'refCount' 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. */
{
    List *listRepPtr;

    ListGetIntRep(srcPtr, listRepPtr);
    assert(listRepPtr != NULL);
    ListSetIntRep(copyPtr, listRepPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * SetListFromAny --
 *
 *	Convert any object to a list.
 *
 * Value
 *
 *    TCL_OK
 *
 *	Success.  The internal representation of 'objPtr' is set, and the type
 *	of 'objPtr' is 'tclListType'.

 *
 *    TCL_ERROR
 *
 *	An error occured during conversion. An error message is left in the
 *	interpreter's result if 'interp' is not NULL.
 *
 *
 *----------------------------------------------------------------------
 */

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;


    /*
     * 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)) {
	Tcl_Obj *keyPtr, *valuePtr;
	Tcl_DictSearch search;
	int done, 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);

	listRepPtr = AttemptNewList(interp, size > 0 ? 2*size : 1, NULL);
	if (!listRepPtr) {
	    return TCL_ERROR;
	}
	listRepPtr->elemCount = 2 * size;





	/*
	 * Populate the list representation.
	 */

	elemPtrs = &listRepPtr->elements;
	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 {
	int estCount;
	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. */

	listRepPtr = AttemptNewList(interp, estCount, NULL);
	if (listRepPtr == NULL) {
	    return TCL_ERROR;
	}
	elemPtrs = &listRepPtr->elements;




	/*
	 * Each iteration, parse and store a list element.
	 */

	while (nextElem < limit) {
	    const char *elemStart;
	    char *check;
	    size_t elemSize;
	    int literal;

	    if (TCL_OK != TclFindElement(interp, nextElem, limit - nextElem,
		    &elemStart, &nextElem, &elemSize, &literal)) {
	    fail:
		while (--elemPtrs >= &listRepPtr->elements) {
		    Tcl_DecrRefCount(*elemPtrs);
		}
		Tcl_Free(listRepPtr);
		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) {
		    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. */
	}


 	listRepPtr->elemCount = elemPtrs - &listRepPtr->elements;
    }



    /*
     * 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.
     */







    ListSetIntRep(objPtr, listRepPtr);




    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfList --
 *
 *	Update the string representation for a list object.
 *
 *	Any previously-exising 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. */
{
#   define LOCAL_SIZE 64
    char localFlags[LOCAL_SIZE], *flagPtr = NULL;
    int numElems, i;
    size_t length, bytesNeeded = 0;
    const char *elem, *start;
    char *dst;
    Tcl_Obj **elemPtrs;
    List *listRepPtr;

    ListGetIntRep(listPtr, listRepPtr);

    assert(listRepPtr != NULL);

    numElems = listRepPtr->elemCount;

    /*
     * 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].













     */




    listRepPtr->canonicalFlag = 1;

    /*
     * Handle empty list case first, so rest of the routine is simpler.
     */

    if (numElems == 0) {
	Tcl_InitStringRep(listPtr, NULL, 0);
	return;
    }

    /*
     * Pass 1: estimate space, gather flags.
     */

    if (numElems <= LOCAL_SIZE) {
	flagPtr = localFlags;
    } else {
	/*
	 * 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);



    }
    bytesNeeded += numElems - 1;

    /*
     * Pass 2: copy into string rep buffer.
     */

    start = dst = Tcl_InitStringRep(listPtr, 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);

    if (flagPtr != localFlags) {
	Tcl_Free(flagPtr);
    }
}
























































/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|








<



|
|


<
|
<
<
<
|

<
>
|
|
|
|
|
>
|
|
|
<
|
>
>
|
|


|










|
>
>

|
<
|
<
|
>
>
|
<

<
|
|
<




>


|
|
|

|

>
|
|
|
<
|
|
|
|
|
|
|
|
>
|
|
|
>
|

>
>
>
>
|
>
|
>







|
>
>
>

|
|
|
<
>
|
|

<
<
<
|
|
|
>

>
>
|
<
|
|

|
<
<
|
<
|
<
>
|
|



<



|
|
|
|
|
<

|
>
>
>
>
>
>
>
|
|

|



<
<
<
|
<
<
<
|
>
|
<
<
<

|
>
|
|
|
<
<
|
<
<
<
<
<
<
<
|
<
<
<



|
|

|
|
|
>
>
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>

>
>
|
<
|
>
|
|
|
<
>
>
>
>
>
|
>
>
>
|
<
<
<
|
<
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|

<
<
<
<
|
>
>
>
>
|
<
>
|
>
|
|
<
|
|
>
|
|
>
|
|
<
<
<
<
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
|
<
<
>
>
|
<
|

>
>
>
>
>
>
|
<
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
|
|
<
<
>
>
|
>
>
>
>
|
<
|
<
|
>
|
|
>
>
|
|
>
>
>
|
|
>
>
>
|
>
>
>
>
>
>
>
>
|
|
>
|
<
<
>

>
>
>
>
|
<
>
|
<
<
|
>
|
>
>
>
>
>
>
>
>
>

|
|
|
|
|
|
|
>
>
|
<
>
>
>
>
>
>
>
|
>
>
>
|
|
>
>
>
>
>

>
>
>
|
<
|
>
|
>
>

|
>
>
>
>
|
<
<
>
|
|
>
>
>
>
>
>
>
>
>
>
|
<
|
<
>
|
<
<
>
>
>
>
|
>
|
>
>
|
>
>
>
>
>
|
|
<

>
|
>
>
>

|
>
|
<
>
>
>
|
|
>
>
>
>
>
>

|

>
|
|
|
|
|
>
|
|
>
>

|
<
>

>
>
>

>
|
>
>
>
>
>
>
|
>
|
>
|
<
>

>
>
>
>
>
>
>
|
<
|
|
>
>
>
>
>
>
>
>
>
|
<
|
<
>
>
>
>
|
<
|
>
>
>
>
>
|
>
>
>
>
>
>
|
<
<
<
>
>
>
>
>
>
>
|
<

<
|
>
|
<

|
>
>
>
>
>
>
|
>
|
>
>
>
|
|
>
|
>
>








|

|
|
|
|

|
|
<
<

|
>
>
>
>
>



<



|
|

<
|

|
>




>
|

|
|
<
|



<
|














|


|
|
>

<
|

|
<
<
<
<
|
<

|





|

|
|

|
>
>
>

<
<
>
|

>
>
>
>
|
|

<


<



|
|



|
>

>
>
>
|
|
|
>
|
<
<
>
|
<
<
<
<
<
>
>
>
|
>
>
|
|
|
|
>
>
>
>
|
<
|
|
>
>
>

>
>
>
|

<



|






|
|
|



>
|
>

>

|
>

>
>
>
>
>
>
|
<
|
>
>
>
>
>
>
|
>
>
>
|
>
|
>
|
|
|







|



|
>
>
|

|
>

<
>
|
>
>
>
>



<



|
|
|

|

|
|

<







|
<
|
<
>
>
>
>
>
>
>
>
>
|
<
|
|
|
|
>

|
|
|
|
|
|
<
|
|
|
>
>
>
>
>
>
>
>

|
|
|

|
|
|
>
>
>
>
>
|










|
|
>
|

<
>
|
>
|
|
<
<
|
<
<
|

|
|
|

<
<
<
|
<
|
|
>
|
|
>
>

<
<
<
<
<
<
<


<



|
|


|

|
|
|
|
>
>




|



|
|

|





|



|



|






|
<

>
>
>
>
>
>
>







|






|
|










|
|


|




>
>
>
>
>
>
>
>
|
|



|
>
|
|







|
|
|



|
|
|

|

|
|





|
|
|
|


|
|

|

|
|
|



|
|
|
|
|
|
|
|
>
|
|
|


<
<
|
>






|
>
|

|
|
|
<

<
<
<
|
|
<
<

|
<
|
|
|
>
>
>
>
>
>
|
>
>
>
|
<
<
<
<
|
<
<
<
|
>
>
>








|
|





|





|
|
>
|
|
>
|

>
|
|

|
|







|

<
<
<
|
<
|
<
<
<
<
<
|
|
|
<
>
|
>

>
|
>
|
|
<
>

<
<
<
<
<
<
<
<
<


<




|

|
|


>
>
>
<
<
<
<

<
|
<

|



<
<
<
<
|
<
<
<
<
<
<
<
<
|
|
<
<
<
|
<
<
<
|

<
|
<
|
<


|

|





|
>

>

>
|
|
<
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
|
|
<
<
<
<

<
<
<
|
|


|
>

|

<
<
<
<
<
|

<
<
<
|
<
<
<
<
<
|
<









|
|

|
>

>





<


|

|

<
<
|
|
|
|
|
<
|
|
|
>








|


|
>

>
|



<


|
|

|
|
<
|
<







|

|
<
|
<
|
<
>

|
<
|
<
|



<





<

>









|


|
>











>
|
|


|
>
>
>

>
|
|
<

|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
<










>
|
<


|
>
>

>
|
|
<




|





|


|











|
<
<
<
<










>
|

>
>







>
>
>
>
>
>
|
>
>
>
>










|










<


|



|
|



|

<
|
|

|





>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
<

<
|
<


|



<
|
<




<
|
<
<


<




>
>
>







|









|





|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	    '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
 *
 * 	    'listPtr' is not a valid list. An error message is left in the
 * 	    interpreter's result if 'interp' is not NULL.
 *
 *  Effect
 *
 * 	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 *listObj,		/* List object to index into. */
    Tcl_Size index,		/* Index of element to return. */
    Tcl_Obj **objPtrPtr)	/* The resulting Tcl_Obj* is stored here. */
{

    Tcl_Obj **elemObjs;



    Tcl_Size numElems;


    /* 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);
    }


    if (TclListObjGetElements(interp, listObj, &numElems, &elemObjs) != TCL_OK) {
	return TCL_ERROR;
    }
    if ((index < 0) || (index >= numElems)) {
	*objPtrPtr = NULL;
    } else {
	*objPtrPtr = elemObjs[index];
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjLength --
 *
 *	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.
 *
 * Results:

 *	The return value is normally TCL_OK; in this case *lenPtr will be set

 *	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.

 *

 * Side effects:
 *	The possible conversion of the argument object to a list object.

 *
 *----------------------------------------------------------------------
 */

#undef Tcl_ListObjLength
int
Tcl_ListObjLength(
    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. */
{
    ListRep listRep;

    /* Empty string => empty list. Avoid unnecessary shimmering */
    if (listObj->bytes == &tclEmptyString) {
	*lenPtr = 0;
	return TCL_OK;

    }

    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)
{
    ListRep listRep;
    ListObjGetRep(listPtr, &listRep);

    return ListRepLength(&listRep);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ListObjReplace --
 *
 *	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 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 first.
 *



 *	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
 *	list object and 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 ref counts of the objc elements in objv are incremented since the

 *	resulting list now refers to them. Similarly, the ref counts for

 *	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 *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 */

{
    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(listObj)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace");
    }




    if (TclObjTypeHasProc(listObj, replaceProc)) {



	return TclObjTypeReplace(interp, listObj, first,
		numToDelete, numToInsert, insertObjs);
    }




    if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {
	/* Cannot be converted to a list */
	return TCL_ERROR;
    }



    /* Make limits sane */







    origListLen = ListRepLength(&listRep);



    if (first < 0) {
	first = 0;
    }
    if (first > origListLen) {
	first = origListLen;	/* So we'll insert after last element. */
    }
    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

     * 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

     *   (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.
     */




    /* Note: do not do TclInvalidateStringRep as yet in case there are errors */



    /* 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);
	}





	/*
	 * 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

	 * 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) */

		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 (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);
		}




	    }


	    ListObjReplaceRepAndInvalidate(listObj, &listRep);
	    return TCL_OK;
	}

    }

    /* Just for readability of the code */
    lenChange = numToInsert - numToDelete;
    leadSegmentLen = first;
    tailSegmentLen = origListLen - (first + numToDelete);
    numFreeSlots = listRep.storePtr->numAllocated - listRep.storePtr->numUsed;

    /*

     * 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 =


	    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);
    }



    /*
     * 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],


		    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;
	}

	LISTREP_CHECK(&newRep);
	ListObjReplaceRepAndInvalidate(listObj, &newRep);


	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?
     */

    /* 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)];


    /*
     * 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
     * start of the ListStore storage area.

     *
     * leadShift - how much to shift the lead segment
     * tailShift - how much to shift the tail segment
     * insertTarget - index where to insert.
     */

    if (lenChange == 0) {
	/* T:listrep-1.{12,15,19},3.{23,28,33}. Exact fit */
	leadShift = 0;
	tailShift = 0;
    } else if (lenChange < 0) {
	/*


	 * 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;
	}

    } else {

	LIST_ASSERT(lenChange > 0); /* Reminder */



	/*
	 * 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;

	    /*
	     * Redistribute the remaining free space between the front and
	     * 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 (finalFreeSpace > 1 && (tailSpace == 0 || tailSegmentLen == 0)) {
		Tcl_Size postShiftLeadSpace = leadSpace - lenChange;
		if (postShiftLeadSpace > (finalFreeSpace/2)) {

		    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;
	    /*
	     * See comments above. This is analogous.
	     */
	    if (finalFreeSpace > 1 && (leadSpace == 0 || leadSegmentLen == 0)) {
		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 {
	    /*
	     * Both lead and tail need to be shifted to make room.

	     * Divide remaining free space equally between front and back.
	     */
	    /* T:listrep-3.{9,13,31,40} */
	    LIST_ASSERT(leadSpace < lenChange);
	    LIST_ASSERT(tailSpace < lenChange);

	    /*
	     * 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;

		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 */
	}

    }

    /* 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 *));
	}

	if (leadSegmentLen != 0) {

	    /* T:listrep-1.{3,6,16,18,21},3.{19,20,34} */
	    memmove(&listObjs[leadShift],
		    &listObjs[0],
		    leadSegmentLen * sizeof(Tcl_Obj *));
	}

    } 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 *));
	}



    }
    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 *));
    }



    listRep.storePtr->firstUsed += leadShift;
    listRep.storePtr->numUsed = origListLen + lenChange;
    listRep.storePtr->flags = 0;


    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 --
 *
 *	This procedure handles the 'lindex' command when objc==3.
 *
 * 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.
 *
 * Side effects:
 *	None.


 *
 * 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 *listObj,		/* List being unpacked. */
    Tcl_Obj *argObj)		/* Index or index list. */
{

    Tcl_Size index;		/* Index into the list. */
    Tcl_Obj *indexListCopy;
    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.
     * see TIP#22 and TIP#33 for the details.
     */
    if (!TclHasInternalRep(argObj, &tclListType)
	    && TclGetIntForIndexM(NULL, argObj, TCL_SIZE_MAX - 1,

		    &index) == TCL_OK) {
	/*
	 * argPtr designates a single index.
	 */

	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, argObj);
    if (indexListCopy == NULL) {
	/*
	 * 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, listObj, 1, &argObj);
    }
    TclListObjGetElements(interp, indexListCopy, &numIndexObjs, &indexObjs);




    listObj = TclLindexFlat(interp, listObj, numIndexObjs, indexObjs);

    Tcl_DecrRefCount(indexListCopy);
    return listObj;
}

/*
 *----------------------------------------------------------------------
 *
 * TclLindexFlat --
 *
 *	This procedure is the core of the 'lindex' command, with all index
 *	arguments presented as a flat list.
 *
 * 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.
 *


 * 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_Obj *
TclLindexFlat(
    Tcl_Interp *interp,		/* Tcl interpreter. */
    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 status;
    Tcl_Size i;

    /* Handle AbstractList as special case */
    if (TclObjTypeHasProc(listObj,indexProc)) {
	Tcl_Size listLen = TclObjTypeLength(listObj);
	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) {


		// TODO: ???
	    }





	    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;
    }


    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);
	    return NULL;
	}


	if (TclGetIntForIndexM(interp, indexArray[i], /*endValue*/ listLen-1,
		&index) == TCL_OK) {
	    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],
			    TCL_SIZE_MAX - 1, &index) != TCL_OK) {
			Tcl_DecrRefCount(listObj);
			return NULL;
		    }
		}
		Tcl_DecrRefCount(listObj);
		TclNewObj(listObj);
		Tcl_IncrRefCount(listObj);
	    } else {
		Tcl_Obj *itemObj;
		/*
		 * 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;
		    }

		}

		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 --
 *
 *	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.
 *
 * 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.
 *
 * Side effects:
 *	None.
 *

 * 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 *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'. */
{
    Tcl_Size indexCount = 0;   /* Number of indices in the index list. */
    Tcl_Obj **indices = NULL;	/* Vector of indices in the index list. */
    Tcl_Obj *retValueObj;	/* Pointer to the list to be returned. */
    Tcl_Size index;            /* Current index in the list - discarded. */
    Tcl_Obj *indexListCopy;


    /*
     * 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.
     */

    if (!TclHasInternalRep(indexArgObj, &tclListType)

	    && TclGetIntForIndexM(NULL, indexArgObj, TCL_SIZE_MAX - 1, &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. */

	    /* 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,indexArgObj);
	if (!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 {
	    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 perform the actual lset operation.
		 */

		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.
 *
 * 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.
 *

 * 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


 *	point, the reference count will be 1 for either case, so that the


 *	object will appear to be unshared.
 *
 *	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.
 *



 *	If no error occurs, the reference count of the original object is

 *	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.)
 *







 *----------------------------------------------------------------------
 */

Tcl_Obj *
TclLsetFlat(
    Tcl_Interp *interp,		/* Tcl interpreter. */
    Tcl_Obj *listObj,		/* Pointer to the list being modified. */
    Tcl_Size indexCount,	/* Number of index args. */
    Tcl_Obj *const indexArray[],
				/* Index args. */
    Tcl_Obj *valueObj)		/* Value arg to 'lset' or NULL to 'lpop'. */
{
    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 valueObj just in case.
     */

    if (indexCount == 0) {
	if (valueObj != NULL) {
	    Tcl_IncrRefCount(valueObj);
	}
	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 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 listObj and
     * all elements to be unchanged.
     */

    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.
     */

    retValueObj = subListObj;

    result = TCL_OK;

    /* Allocate if static array for pending invalidations is too small */
    if (indexCount > (int) (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 {
	Tcl_Size elemCount;
	Tcl_Obj *parentList, **elemPtrs;

	/*
	 * Check for the possible error conditions...
	 */

	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) {
	    /* ...the index we're trying to use isn't an index at all. */
	    result = TCL_ERROR;
	    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 < 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" "OUTOFRANGE", (void *)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.
	 */

	if (--indexCount) {
	    parentList = subListObj;
	    if (index == elemCount) {
		TclNewObj(subListObj);
	    } else {
		subListObj = elemPtrs[index];
	    }
	    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 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 == elemCount) {
		Tcl_ListObjAppendElement(NULL, parentList, subListObj);
	    } else {
		TclListObjSetElement(NULL, parentList, index, subListObj);
	    }
	    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 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 (via a
	     * little internalrep surgery) so we can spoil them at that
	     * time.
	     */



	    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 valueObj. On success, we need to invalidate
     * the string representations of intermediate lists whose contained
     * list element would have changed.
     */
    if (result == TCL_OK) {
	while (numPendingInvalidates > 0) {
	    Tcl_Obj *objPtr;





	    --numPendingInvalidates;
	    objPtr = pendingInvalidatesPtr[numPendingInvalidates];



	    if (result == TCL_OK) {

		/*
		 * 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);
	    }




	}



    }

    if (pendingInvalidatesPtr != pendingInvalidates) {
	Tcl_Free(pendingInvalidatesPtr);
    }

    if (result != TCL_OK) {
	/*
	 * Error return; message is already in interp. Clean up any excess
	 * memory.
	 */

	if (retValueObj != listObj) {
	    Tcl_DecrRefCount(retValueObj);
	}
	return NULL;
    }

    /*
     * 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, 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, subListObj, index, valueObj);
	TclInvalidateStringRep(subListObj);
    }
    Tcl_IncrRefCount(retValueObj);
    return retValueObj;
}

/*
 *----------------------------------------------------------------------
 *
 * TclListObjSetElement --
 *
 *	Set a single element of a list to a specified value
 *



 * Results:

 *	The return value is normally TCL_OK. If listObj does not refer to a





 *	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

 *	[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:
 *	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

 *	ref count of the replacement object.
 *









 *----------------------------------------------------------------------
 */

int
TclListObjSetElement(
    Tcl_Interp *interp,		/* Tcl interpreter; used for error reporting
				 * if not NULL. */
    Tcl_Obj *listObj,		/* List object in which element should be
				 * stored. */
    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. */






    /* Ensure that the listObj parameter designates an unshared list. */


    if (Tcl_IsShared(listObj)) {
	Tcl_Panic("%s called with shared object", "TclListObjSetElement");
    }





    if (TclListObjGetRep(interp, listObj, &listRep) != TCL_OK) {








	return TCL_ERROR;
    }







    elemCount = ListRepLength(&listRep);


    /* Ensure that the index is in bounds. */

    if ((index < 0) || (index >= elemCount)) {

	if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"index \"%" TCL_SIZE_MODIFIER "d\" out of range", index));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX",
		    "OUTOFRANGE", (void *)NULL);
	}
	return TCL_ERROR;
    }

    /*
     * 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 (listRep.storePtr->refCount > 1) {
	ListRep newInternalRep;

	/* T:listrep-2.{10,13,16}.1 */









	/* TODO - leave extra space? */





	ListRepClone(&listRep, &newInternalRep, LISTREP_PANIC_ON_FAIL);
	listRep = newInternalRep;
    } /* else T:listrep-1.{12.1,15.1,19.1} */








    /* Retrieve element array AFTER potential cloning above */
    ListRepElements(&listRep, elemCount, elemPtrs);

    /*
     * 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]);





    elemPtrs[index] = valueObj;




    /* Internal rep may be cloned so replace */





    ListObjReplaceRepAndInvalidate(listObj, &listRep);


    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * FreeListInternalRep --
 *
 *	Deallocate the storage associated with a list object's internal
 *	representation.
 *
 * 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 *listObj)		/* List object with internal rep to free. */
{
    ListRep listRep;



    ListObjGetRep(listObj, &listRep);
    if (listRep.storePtr->refCount-- <= 1) {
	ObjArrayDecrRefs(
	    listRep.storePtr->slots,
	    listRep.storePtr->firstUsed, listRep.storePtr->numUsed);

	Tcl_Free(listRep.storePtr);
    }
    if (listRep.spanPtr) {
	ListSpanDecrRefs(listRep.spanPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * DupListInternalRep --
 *
 *	Initialize the internal representation of a list Tcl_Obj to share the
 *	internal representation of an existing list object.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The reference count of the List internal rep is incremented.
 *
 *----------------------------------------------------------------------
 */

static void
DupListInternalRep(
    Tcl_Obj *srcObj,		/* Object with internal rep to copy. */
    Tcl_Obj *copyObj)		/* Object with internal rep to set. */
{
    ListRep listRep;
    ListObjGetRep(srcObj, &listRep);

    ListObjOverwriteRep(copyObj, &listRep);

}

/*
 *----------------------------------------------------------------------
 *
 * SetListFromAny --
 *
 *	Attempt to generate a list internal form for the Tcl object "objPtr".
 *
 * Results:

 *	The return value is TCL_OK or TCL_ERROR. If an error occurs during

 *	conversion, an error message is left in the interpreter's result

 *	unless "interp" is NULL.
 *
 * Side effects:

 *	If no error occurs, a list is stored as "objPtr"s internal

 *	representation.
 *
 *----------------------------------------------------------------------
 */

static int
SetListFromAny(
    Tcl_Interp *interp,		/* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr)		/* The object to convert. */
{

    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) && TclHasInternalRep(objPtr, &tclDictType)) {
	Tcl_Obj *keyPtr, *valuePtr;
	Tcl_DictSearch search;
	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? */
	if (ListRepInitAttempt(interp, size > 0 ? 2 * size : 1, NULL,
		&listRep) != TCL_OK) {
	    return TCL_ERROR;
	}

	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. */


	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 {
	Tcl_Size estCount, 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? */
	if (ListRepInitAttempt(interp, estCount, 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, parse and store a list element. */


	while (nextElem < limit) {
	    const char *elemStart;
	    char *check;
	    Tcl_Size elemSize;
	    int literal;

	    if (TCL_OK != TclFindElement(interp, nextElem, limit - nextElem,
		    &elemStart, &nextElem, &elemSize, &literal)) {
	    fail:
		while (--elemPtrs >= listRep.storePtr->slots) {
		    Tcl_DecrRefCount(*elemPtrs);
		}
		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) {
		MemoryAllocationError(interp, elemSize);




		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 =
	    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);
    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-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 *listObj)		/* List object with string rep to update. */
{
#   define LOCAL_SIZE 64
    char localFlags[LOCAL_SIZE], *flagPtr = NULL;
    Tcl_Size numElems, i, length;
    size_t bytesNeeded = 0;
    const char *elem, *start;
    char *dst;
    Tcl_Obj **elemPtrs;
    ListRep listRep;


    ListObjGetRep(listObj, &listRep);
    LISTREP_CHECK(&listRep);

    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;
    }



    /* Handle empty list case first, so rest of the routine is simpler. */


    if (numElems == 0) {
	Tcl_InitStringRep(listObj, NULL, 0);
	return;
    }


    /* Pass 1: estimate space, gather flags. */


    if (numElems <= LOCAL_SIZE) {
	flagPtr = localFlags;
    } else {

	/* We know numElems <= LIST_MAX, so this is safe. */


	flagPtr = (char *)Tcl_Alloc(numElems);
    }

    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(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(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
/*
 * 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.
 *
 * 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,
			    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









|
|



















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 © 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 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
 */

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. */
    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) {
	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;
	    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







|
|
|














|














|







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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. */
    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 == (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
	     */

	    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
 *----------------------------------------------------------------------
 */

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
				 * by prior call to TclRegisterLiteral() */
{
    if (index >= (size_t) envPtr->literalArrayNext) {
	return NULL;
    }
    return envPtr->literalArrayPtr[index].objPtr;
}

/*
 *----------------------------------------------------------------------







|


|







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. */
    Tcl_Size index)		/* Index of the desired literal, as returned
				 * by prior call to TclRegisterLiteral() */
{
    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
 *	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
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
				 * 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
				 * 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) {
	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.







|






|





|











|







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 /* 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. */
    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 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 < 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
		Tcl_Free((void *)bytes);
	    }
	    objIndex = (localPtr - envPtr->literalArrayPtr);
#ifdef TCL_COMPILE_DEBUG
	    TclVerifyLocalLiteralTable(envPtr);
#endif /*TCL_COMPILE_DEBUG*/




	    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
     * 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;







>
>
>






|







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 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
    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*/




    return objIndex;
}

#ifdef TCL_COMPILE_DEBUG
/*
 *----------------------------------------------------------------------
 *







>
>
>
>







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
    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;

    const char *bytes;
    Tcl_Obj *newObjPtr;

    lPtr = &envPtr->literalArrayPtr[index];

    /*
     * To avoid unwanted sharing we need to copy the object and remove it from







|
>







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;
    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
				 * 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;

    if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) {
	ExpandLocalLiteralArray(envPtr);
    }
    objIndex = envPtr->literalArrayNext;
    envPtr->literalArrayNext++;





    lPtr = &envPtr->literalArrayPtr[objIndex];
    lPtr->objPtr = objPtr;
    Tcl_IncrRefCount(objPtr);
    lPtr->refCount = TCL_INDEX_NONE;	/* i.e., unused */
    lPtr->nextPtr = NULL;








|






>
>
>
>







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;
    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
 * 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
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;

    objIndex = TclAddLiteralObj(envPtr, objPtr, &localPtr);

    /*
     * Add the literal to the local table.
     */








|








|







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 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;
    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
				 * previously created by a call to
				 * TclRegisterLiteral. */
{
    Interp *iPtr = (Interp *) interp;
    LiteralTable *globalTablePtr;
    LiteralEntry *entryPtr, *prevPtr;
    const char *bytes;
    size_t length, index;


    if (iPtr == NULL) {
	goto done;
    }

    globalTablePtr = &iPtr->literalTable;
    bytes = TclGetStringFromObj(objPtr, &length);







|
>







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 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
				/* Local or global table to enlarge. */
{
    LiteralEntry **oldBuckets;
    LiteralEntry **oldChainPtr, **newChainPtr;
    LiteralEntry *entryPtr;
    LiteralEntry **bucketPtr;
    const char *bytes;
    size_t oldSize, count, index, length;


    oldSize = tablePtr->numBuckets;
    oldBuckets = tablePtr->buckets;

    /*
     * Allocate and initialize the new bucket array, and set up hashing
     * constants for new array size.







|
>







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;
    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
 *	TclSetCmdNameObj()).
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Resets the internal representation of the CmdName Tcl_Obj
 *	using TclFreeIntRep().
 *
 *----------------------------------------------------------------------
 */

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);

    if (literalObjPtr != NULL) {
	if (TclHasIntRep(literalObjPtr, &tclCmdNameType)) {
	    TclFreeIntRep(literalObjPtr);
	}
	/* Balance the refcount effects of TclCreateLiteral() above */
	Tcl_IncrRefCount(literalObjPtr);
	TclReleaseLiteral(interp, literalObjPtr);
    }
}








|















|


|
|







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 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), TCL_INDEX_NONE, NULL, nsPtr, 0, NULL);

    if (literalObjPtr != NULL) {
	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
    }

    /*
     * 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",
	    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",
		i, count[i]);
	p += strlen(p);
    }
    sprintf(p, "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);
    return result;
}
#endif /*TCL_COMPILE_STATS*/

#ifdef TCL_COMPILE_DEBUG
/*
 *----------------------------------------------------------------------







|



|



|


|







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);
    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++) {
	snprintf(p, 60, "number of buckets with %" TCL_Z_MODIFIER "u entries: %" TCL_Z_MODIFIER "u\n",
		i, count[i]);
	p += strlen(p);
    }
    snprintf(p, 60, "number of buckets with %d or more entries: %" TCL_Z_MODIFIER "u\n",
	    NUM_COUNTERS, overflow);
    p += strlen(p);
    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
/*
 * 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.
 *
 * 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
 * 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
 * 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
				 * is loaded statically. Malloc-ed. */
    char *packageName;		/* Name of package prefix for the package,
				 * 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;
				/* Initialization function to call to
				 * incorporate this package into a trusted
				 * interpreter. */
    Tcl_PackageInitProc *safeInitProc;
				/* Initialization function to call to
				 * incorporate this package into a safe
				 * interpreter (one that will execute
				 * untrusted scripts). NULL means the package
				 * can't be used in unsafe interpreters. */
    Tcl_PackageUnloadProc *unloadProc;
				/* Finalisation function to unload a package
				 * from a trusted interpreter. NULL means that
				 * the package cannot be unloaded. */
    Tcl_PackageUnloadProc *safeUnloadProc;
				/* Finalisation function to unload a package
				 * from a safe interpreter. NULL means that
				 * the package cannot be unloaded. */
    int interpRefCount;		/* How many times the package has been loaded
				 * in trusted interpreters. */
    int safeInterpRefCount;	/* How many times the package has been loaded
				 * in safe interpreters. */
    struct LoadedPackage *nextPtr;
				/* Next in list of all packages loaded into
				 * this application process. NULL means end of
				 * list. */
} LoadedPackage;

/*
 * TCL_THREADS
 * There is a global list of packages that is anchored at firstPackagePtr.
 * Access to this list is governed by a mutex.
 */

static LoadedPackage *firstPackagePtr = NULL;
				/* First in list of all packages loaded into
				 * this process. */

TCL_DECLARE_MUTEX(packageMutex)

/*
 * The following structure represents a particular package 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).
 */

typedef struct InterpPackage {
    LoadedPackage *pkgPtr;	/* Points to detailed information about
				 * package. */
    struct InterpPackage *nextPtr;
				/* Next package in this interpreter, or NULL
				 * for end of list. */
} InterpPackage;

/*
 * Prototypes for functions that are private to this file:
 */

static void		LoadCleanupProc(ClientData clientData,
			    Tcl_Interp *interp);













/*
 *----------------------------------------------------------------------
 *
 * Tcl_LoadObjCmd --
 *
 *	This function is invoked to process the "load" Tcl command. See the






|







>

|

|
|
<
<


|
|
|

|
<
<





|

|

|

|

|

|
|

|
|
|

|
|

|

|
|


|



|



|
|


|


|



|


|
|
|
|
|

|





|
|
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20


21
22
23
24
25
26
27


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*
 * tclLoad.c --
 *
 *	This file provides the generic portion (those that are the same on all
 *	platforms) of Tcl's dynamic loading facilities.
 *
 * 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 library that has been loaded either
 * dynamically (with the "load" command) or statically (as indicated by a call
 * to Tcl_StaticLibrary). All such libraries are linked together into a
 * single list for the process.


 */

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 *prefix;		/* Prefix for the library.


				 * 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_LibraryInitProc *initProc;
				/* Initialization function to call to
				 * incorporate this library into a trusted
				 * interpreter. */
    Tcl_LibraryInitProc *safeInitProc;
				/* Initialization function to call to
				 * incorporate this library into a safe
				 * interpreter (one that will execute
				 * untrusted scripts). NULL means the library
				 * can't be used in unsafe interpreters. */
    Tcl_LibraryUnloadProc *unloadProc;
				/* Finalization function to unload a library
				 * from a trusted interpreter. NULL means that
				 * the library cannot be unloaded. */
    Tcl_LibraryUnloadProc *safeUnloadProc;
				/* Finalization function to unload a library
				 * from a safe interpreter. NULL means that
				 * the library cannot be unloaded. */
    int interpRefCount;		/* How many times the library has been loaded
				 * in trusted interpreters. */
    int safeInterpRefCount;	/* How many times the library has been loaded
				 * in safe interpreters. */
    struct LoadedLibrary *nextPtr;
				/* Next in list of all libraries loaded into
				 * this application process. NULL means end of
				 * list. */
} LoadedLibrary;

/*
 * TCL_THREADS
 * There is a global list of libraries that is anchored at firstLibraryPtr.
 * Access to this list is governed by a mutex.
 */

static LoadedLibrary *firstLibraryPtr = NULL;
				/* First in list of all libraries loaded into
				 * this process. */

TCL_DECLARE_MUTEX(libraryMutex)

/*
 * 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 library (if any).
 */

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. */
} InterpLibrary;

/*
 * Prototypes for functions that are private to this file:
 */

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
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;
    Tcl_DString unloadName, safeUnloadName;
    InterpPackage *ipFirstPtr, *ipPtr;
    int code, namesMatch, filesMatch, offset;
    const char *symbols[2];
    Tcl_PackageInitProc *initProc;
    const char *p, *fullFileName, *packageName;
    Tcl_LoadHandle loadHandle;
    Tcl_UniChar ch = 0;
    size_t len;
    int index, flags = 0;
    Tcl_Obj *const *savedobjv = objv;
    static const char *const options[] = {
	"-global",		"-lazy",		"--",	NULL
    };
    enum loadOptionsEnum {
	LOAD_GLOBAL,	LOAD_LAZY,	LOAD_LAST
    };

    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) {
	    flags |= TCL_LOAD_GLOBAL;
	} else if (LOAD_LAZY == (enum loadOptionsEnum) index) {
	    flags |= TCL_LOAD_LAZY;
	} else {
		break;
	}
    }
    if ((objc < 2) || (objc > 4)) {
	Tcl_WrongNumArgs(interp, 1, savedobjv, "?-global? ?-lazy? ?--? fileName ?packageName? ?interp?");
	return TCL_ERROR;
    }
    if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
	return TCL_ERROR;
    }
    fullFileName = TclGetString(objv[1]);

    Tcl_DStringInit(&pkgName);
    Tcl_DStringInit(&initName);
    Tcl_DStringInit(&safeInitName);
    Tcl_DStringInit(&unloadName);
    Tcl_DStringInit(&safeUnloadName);
    Tcl_DStringInit(&tmp);

    packageName = NULL;
    if (objc >= 3) {
	packageName = TclGetString(objv[2]);
	if (packageName[0] == '\0') {
	    packageName = NULL;
	}
    }
    if ((fullFileName[0] == 0) && (packageName == NULL)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"must specify either file name or package name", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOLIBRARY",
		NULL);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * Figure out which interpreter we're going to load the package 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
     * 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.
     */

    Tcl_MutexLock(&packageMutex);

    defaultPtr = NULL;
    for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
	if (packageName == NULL) {
	    namesMatch = 0;
	} else {
	    TclDStringClear(&pkgName);
	    Tcl_DStringAppend(&pkgName, packageName, -1);
	    TclDStringClear(&tmp);
	    Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1);
	    Tcl_UtfToLower(Tcl_DStringValue(&pkgName));
	    Tcl_UtfToLower(Tcl_DStringValue(&tmp));
	    if (strcmp(Tcl_DStringValue(&tmp),
		    Tcl_DStringValue(&pkgName)) == 0) {
		namesMatch = 1;
	    } else {
		namesMatch = 0;
	    }
	}
	TclDStringClear(&pkgName);

	filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0);
	if (filesMatch && (namesMatch || (packageName == NULL))) {
	    break;
	}
	if (namesMatch && (fullFileName[0] == 0)) {
	    defaultPtr = pkgPtr;
	}
	if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
	    /*
	     * Can't have two different packages loaded from the same file.
	     */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "file \"%s\" is already loaded for package \"%s\"",
		    fullFileName, pkgPtr->packageName));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD",
		    "SPLITPERSONALITY", NULL);
	    code = TCL_ERROR;
	    Tcl_MutexUnlock(&packageMutex);
	    goto done;
	}
    }
    Tcl_MutexUnlock(&packageMutex);
    if (pkgPtr == NULL) {
	pkgPtr = defaultPtr;
    }

    /*
     * Scan through the list of packages already loaded in the target
     * interpreter. If the package we want is already loaded there, then
     * there's nothing for us to do.
     */

    if (pkgPtr != NULL) {
	ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL);
	for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    if (ipPtr->pkgPtr == pkgPtr) {
		code = TCL_OK;
		goto done;
	    }
	}
    }

    if (pkgPtr == NULL) {
	/*
	 * The desired file isn't currently loaded, so load it. It's an error
	 * if the desired package is a static one.
	 */

	if (fullFileName[0] == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "package \"%s\" isn't loaded statically", packageName));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOTSTATIC",
		    NULL);
	    code = TCL_ERROR;
	    goto done;
	}

	/*
	 * Figure out the module name if it wasn't provided explicitly.
	 */

	if (packageName != NULL) {
	    Tcl_DStringAppend(&pkgName, packageName, -1);
	} else {

	    int retc;


	    /*
	     * 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.
		 */

		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;
		}
#endif /* __CYGWIN__ */








		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);
	    }
	}

	/*
	 * 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.
	 */

	Tcl_DStringSetLength(&pkgName,
		Tcl_UtfToTitle(Tcl_DStringValue(&pkgName)));



	/*
	 * Compute the names of the two initialization functions, based on the
	 * package name.
	 */

	TclDStringAppendDString(&initName, &pkgName);
	TclDStringAppendLiteral(&initName, "_Init");
	TclDStringAppendDString(&safeInitName, &pkgName);
	TclDStringAppendLiteral(&safeInitName, "_SafeInit");
	TclDStringAppendDString(&unloadName, &pkgName);
	TclDStringAppendLiteral(&unloadName, "_Unload");
	TclDStringAppendDString(&safeUnloadName, &pkgName);
	TclDStringAppendLiteral(&safeUnloadName, "_SafeUnload");

	/*
	 * Call platform-specific code to load the package and find the two
	 * initialization functions.
	 */

	symbols[0] = Tcl_DStringValue(&initName);
	symbols[1] = NULL;

	Tcl_MutexLock(&packageMutex);
	code = Tcl_LoadFile(interp, objv[1], symbols, flags, &initProc,
		&loadHandle);
	Tcl_MutexUnlock(&packageMutex);
	if (code != TCL_OK) {
	    goto done;
	}

	/*
	 * Create a new record to describe this package.
	 */

	pkgPtr = (LoadedPackage *)Tcl_Alloc(sizeof(LoadedPackage));
	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 *)
		Tcl_FindSymbol(interp, loadHandle,
			Tcl_DStringValue(&safeInitName));
	pkgPtr->unloadProc	   = (Tcl_PackageUnloadProc *)
		Tcl_FindSymbol(interp, loadHandle,
			Tcl_DStringValue(&unloadName));
	pkgPtr->safeUnloadProc	   = (Tcl_PackageUnloadProc *)
		Tcl_FindSymbol(interp, loadHandle,
			Tcl_DStringValue(&safeUnloadName));
	pkgPtr->interpRefCount	   = 0;
	pkgPtr->safeInterpRefCount = 0;

	Tcl_MutexLock(&packageMutex);
	pkgPtr->nextPtr		   = firstPackagePtr;
	firstPackagePtr		   = pkgPtr;
	Tcl_MutexUnlock(&packageMutex);

	/*
	 * 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
     * the safe one, depending on whether or not the interpreter is safe).
     */

    if (Tcl_IsSafe(target)) {
	if (pkgPtr->safeInitProc == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't use package in a safe interpreter: no"
		    " %s_SafeInit procedure", pkgPtr->packageName));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "UNSAFE",
		    NULL);
	    code = TCL_ERROR;
	    goto done;
	}
	code = pkgPtr->safeInitProc(target);
    } else {
	if (pkgPtr->initProc == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't attach package to interpreter: no %s_Init procedure",
		    pkgPtr->packageName));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "ENTRYPOINT",
		    NULL);
	    code = TCL_ERROR;
	    goto done;
	}
	code = pkgPtr->initProc(target);
    }

    /*
     * Test for whether the initialization failed. If so, transfer the error
     * from the target interpreter to the originating one.
     */








|
|

|


|
|



|






|










|

|






|







|






|

|
|
|


|

|

|





|














|
|




|


|


|
|


|
|

|
<
<

|





|

|
|



|



|



|
|

|

|



|
|
|



|
|



|
|

|






|


|




|

|





|


|
|

>
|
>





<
<
<
<
<
<
|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|

>
>
>
>
>
>
>
>
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
|
|
|
|

|
|
>
>



|


|

|

|

|



|






|


|





|


|

|
|
|
|
|
|
|
|


|


|


|
|

|
|
|
|










|




|

|
|

|



|

|

|
|

|



|







126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237


238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
Tcl_LoadObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Interp *target;
    LoadedLibrary *libraryPtr, *defaultPtr;
    Tcl_DString pfx, tmp, initName, safeInitName;
    Tcl_DString unloadName, safeUnloadName;
    InterpLibrary *ipFirstPtr, *ipPtr;
    int code, namesMatch, filesMatch, offset;
    const char *symbols[2];
    Tcl_LibraryInitProc *initProc;
    const char *p, *fullFileName, *prefix;
    Tcl_LoadHandle loadHandle;
    Tcl_UniChar ch = 0;
    size_t len;
    int flags = 0;
    Tcl_Obj *const *savedobjv = objv;
    static const char *const options[] = {
	"-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 == index) {
	    flags |= TCL_LOAD_GLOBAL;
	} else if (LOAD_LAZY == index) {
	    flags |= TCL_LOAD_LAZY;
	} else {
		break;
	}
    }
    if ((objc < 2) || (objc > 4)) {
	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(&pfx);
    Tcl_DStringInit(&initName);
    Tcl_DStringInit(&safeInitName);
    Tcl_DStringInit(&unloadName);
    Tcl_DStringInit(&safeUnloadName);
    Tcl_DStringInit(&tmp);

    prefix = NULL;
    if (objc >= 3) {
	prefix = TclGetString(objv[2]);
	if (prefix[0] == '\0') {
	    prefix = NULL;
	}
    }
    if ((fullFileName[0] == 0) && (prefix == NULL)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"must specify either file name or prefix", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOLIBRARY",
		(char *)NULL);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * 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 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 library with the same prefix.
     */

    Tcl_MutexLock(&libraryMutex);

    defaultPtr = NULL;
    for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) {
	if (prefix == NULL) {
	    namesMatch = 0;
	} else {
	    TclDStringClear(&pfx);
	    Tcl_DStringAppend(&pfx, prefix, -1);
	    TclDStringClear(&tmp);
	    Tcl_DStringAppend(&tmp, libraryPtr->prefix, -1);


	    if (strcmp(Tcl_DStringValue(&tmp),
		    Tcl_DStringValue(&pfx)) == 0) {
		namesMatch = 1;
	    } else {
		namesMatch = 0;
	    }
	}
	TclDStringClear(&pfx);

	filesMatch = (strcmp(libraryPtr->fileName, fullFileName) == 0);
	if (filesMatch && (namesMatch || (prefix == NULL))) {
	    break;
	}
	if (namesMatch && (fullFileName[0] == 0)) {
	    defaultPtr = libraryPtr;
	}
	if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
	    /*
	     * Can't have two different libraries loaded from the same file.
	     */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "file \"%s\" is already loaded for prefix \"%s\"",
		    fullFileName, libraryPtr->prefix));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD",
		    "SPLITPERSONALITY", (char *)NULL);
	    code = TCL_ERROR;
	    Tcl_MutexUnlock(&libraryMutex);
	    goto done;
	}
    }
    Tcl_MutexUnlock(&libraryMutex);
    if (libraryPtr == NULL) {
	libraryPtr = defaultPtr;
    }

    /*
     * 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 (libraryPtr != NULL) {
	ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
	for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    if (ipPtr->libraryPtr == libraryPtr) {
		code = TCL_OK;
		goto done;
	    }
	}
    }

    if (libraryPtr == NULL) {
	/*
	 * The desired file isn't currently loaded, so load it. It's an error
	 * if the desired library is a static one.
	 */

	if (fullFileName[0] == 0) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "no library with prefix \"%s\" is loaded statically", prefix));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "NOTSTATIC",
		    (char *)NULL);
	    code = TCL_ERROR;
	    goto done;
	}

	/*
	 * Figure out the prefix if it wasn't provided explicitly.
	 */

	if (prefix != NULL) {
	    Tcl_DStringAppend(&pfx, prefix, -1);
	} else {
	    Tcl_Obj *splitPtr, *pkgGuessPtr;
	    Tcl_Size pElements;
	    const char *pkgGuess;

	    /*
	     * Threading note - this call used to be protected by a mutex.
	     */







	    /*
	     * 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;
	    }
#ifdef __CYGWIN__
	    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);

		if (!Tcl_UniCharIsWordChar(UCHAR(ch))
			|| Tcl_UniCharIsDigit(UCHAR(ch))) {
		    break;
		}
	    }
	    if (p == pkgGuess) {
		Tcl_DecrRefCount(splitPtr);
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't 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 prefix so that the first
	     * character is in caps (or title case) but the others are all
	     * lower-case.
	     */

	    Tcl_DStringSetLength(&pfx,
		    Tcl_UtfToTitle(Tcl_DStringValue(&pfx)));

	}

	/*
	 * Compute the names of the two initialization functions, based on the
	 * prefix.
	 */

	TclDStringAppendDString(&initName, &pfx);
	TclDStringAppendLiteral(&initName, "_Init");
	TclDStringAppendDString(&safeInitName, &pfx);
	TclDStringAppendLiteral(&safeInitName, "_SafeInit");
	TclDStringAppendDString(&unloadName, &pfx);
	TclDStringAppendLiteral(&unloadName, "_Unload");
	TclDStringAppendDString(&safeUnloadName, &pfx);
	TclDStringAppendLiteral(&safeUnloadName, "_SafeUnload");

	/*
	 * Call platform-specific code to load the library and find the two
	 * initialization functions.
	 */

	symbols[0] = Tcl_DStringValue(&initName);
	symbols[1] = NULL;

	Tcl_MutexLock(&libraryMutex);
	code = Tcl_LoadFile(interp, objv[1], symbols, flags, &initProc,
		&loadHandle);
	Tcl_MutexUnlock(&libraryMutex);
	if (code != TCL_OK) {
	    goto done;
	}

	/*
	 * Create a new record to describe this library.
	 */

	libraryPtr = (LoadedLibrary *)Tcl_Alloc(sizeof(LoadedLibrary));
	len = strlen(fullFileName) + 1;
	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));
	libraryPtr->unloadProc	   = (Tcl_LibraryUnloadProc *)
		Tcl_FindSymbol(interp, loadHandle,
			Tcl_DStringValue(&unloadName));
	libraryPtr->safeUnloadProc	   = (Tcl_LibraryUnloadProc *)
		Tcl_FindSymbol(interp, loadHandle,
			Tcl_DStringValue(&safeUnloadName));
	libraryPtr->interpRefCount	   = 0;
	libraryPtr->safeInterpRefCount = 0;

	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 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 (libraryPtr->safeInitProc == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't use library in a safe interpreter: no"
		    " %s_SafeInit procedure", libraryPtr->prefix));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "UNSAFE",
		    (char *)NULL);
	    code = TCL_ERROR;
	    goto done;
	}
	code = libraryPtr->safeInitProc(target);
    } else {
	if (libraryPtr->initProc == NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "can't attach library to interpreter: no %s_Init procedure",
		    libraryPtr->prefix));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LOAD", "ENTRYPOINT",
		    (char *)NULL);
	    code = TCL_ERROR;
	    goto done;
	}
	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
	    iPtr->legacyFreeProc = (void (*) (void))-1;
	}
	Tcl_TransferResult(target, code, interp);
	goto done;
    }

    /*
     * Record the fact that the package has been loaded in the target
     * interpreter.
     *
     * Update the proper reference count.
     */

    Tcl_MutexLock(&packageMutex);
    if (Tcl_IsSafe(target)) {
	pkgPtr->safeInterpRefCount++;
    } else {
	pkgPtr->interpRefCount++;
    }
    Tcl_MutexUnlock(&packageMutex);

    /*
     * Refetch ipFirstPtr: loading the package may have introduced additional
     * static packages at the head of the linked list!
     */

    ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL);
    ipPtr = (InterpPackage *)Tcl_Alloc(sizeof(InterpPackage));
    ipPtr->pkgPtr = pkgPtr;
    ipPtr->nextPtr = ipFirstPtr;
    Tcl_SetAssocData(target, "tclLoad", LoadCleanupProc, ipPtr);

  done:
    Tcl_DStringFree(&pkgName);
    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
 *	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;
    Tcl_PackageUnloadProc *unloadProc;
    InterpPackage *ipFirstPtr, *ipPtr;
    int i, index, code, complain = 1, keepLibrary = 0;
    int trustedRefCount = -1, safeRefCount = -1;
    const char *fullFileName = "";
    const char *packageName;
    static const char *const options[] = {
	"-nocomplain", "-keeplibrary", "--", NULL
    };
    enum unloadOptionsEnum {
	UNLOAD_NOCOMPLAIN, UNLOAD_KEEPLIB, UNLOAD_LAST
    };

    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] == '-') {
		/*







|





|

|

|

|


|
|


|
|
|




|













|



















|
|
<
|
|
<

|





|







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
	    iPtr->legacyFreeProc = (void (*) (void))-1;
	}
	Tcl_TransferResult(target, code, interp);
	goto done;
    }

    /*
     * Record the fact that the library has been loaded in the target
     * interpreter.
     *
     * Update the proper reference count.
     */

    Tcl_MutexLock(&libraryMutex);
    if (Tcl_IsSafe(target)) {
	libraryPtr->safeInterpRefCount++;
    } else {
	libraryPtr->interpRefCount++;
    }
    Tcl_MutexUnlock(&libraryMutex);

    /*
     * Refetch ipFirstPtr: loading the library may have introduced additional
     * static libraries at the head of the linked list!
     */

    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(&pfx);
    Tcl_DStringFree(&initName);
    Tcl_DStringFree(&safeInitName);
    Tcl_DStringFree(&unloadName);
    Tcl_DStringFree(&safeUnloadName);
    Tcl_DStringFree(&tmp);
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UnloadObjCmd --
 *
 *	Implements the 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. */
    LoadedLibrary *libraryPtr;
    Tcl_DString pfx, tmp;

    InterpLibrary *ipFirstPtr, *ipPtr;
    int i, code, complain = 1, keepLibrary = 0;

    const char *fullFileName = "";
    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
		 * must clear the error.
		 */

		Tcl_ResetResult(interp);
		break;
	    }
	}
	switch ((enum unloadOptionsEnum)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?");
	return TCL_ERROR;
    }
    if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
	return TCL_ERROR;
    }

    fullFileName = TclGetString(objv[i]);
    Tcl_DStringInit(&pkgName);
    Tcl_DStringInit(&tmp);

    packageName = NULL;
    if (objc - i >= 2) {
	packageName = TclGetString(objv[i+1]);
	if (packageName[0] == '\0') {
	    packageName = NULL;
	}
    }
    if ((fullFileName[0] == 0) && (packageName == NULL)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"must specify either file name or package name", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NOLIBRARY",
		NULL);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * Figure out which interpreter we're going to load the package 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
     * 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.
     */

    Tcl_MutexLock(&packageMutex);

    defaultPtr = NULL;
    for (pkgPtr = firstPackagePtr; pkgPtr != NULL; pkgPtr = pkgPtr->nextPtr) {
	int namesMatch, filesMatch;

	if (packageName == NULL) {
	    namesMatch = 0;
	} else {
	    TclDStringClear(&pkgName);
	    Tcl_DStringAppend(&pkgName, packageName, -1);
	    TclDStringClear(&tmp);
	    Tcl_DStringAppend(&tmp, pkgPtr->packageName, -1);
	    Tcl_UtfToLower(Tcl_DStringValue(&pkgName));
	    Tcl_UtfToLower(Tcl_DStringValue(&tmp));
	    if (strcmp(Tcl_DStringValue(&tmp),
		    Tcl_DStringValue(&pkgName)) == 0) {
		namesMatch = 1;
	    } else {
		namesMatch = 0;
	    }
	}
	TclDStringClear(&pkgName);

	filesMatch = (strcmp(pkgPtr->fileName, fullFileName) == 0);
	if (filesMatch && (namesMatch || (packageName == NULL))) {
	    break;
	}
	if (namesMatch && (fullFileName[0] == 0)) {
	    defaultPtr = pkgPtr;
	}
	if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
	    break;
	}
    }
    Tcl_MutexUnlock(&packageMutex);
    if (fullFileName[0] == 0) {
	/*
	 * It's an error to try unload a static package.
	 */

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"package \"%s\" is loaded statically and cannot be unloaded",
		packageName));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "STATIC",
		NULL);
	code = TCL_ERROR;
	goto done;
    }
    if (pkgPtr == 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);
	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
     * should proceed with unloading.
     */

    code = TCL_ERROR;
    if (pkgPtr != NULL) {
	ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(target, "tclLoad", NULL);
	for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    if (ipPtr->pkgPtr == pkgPtr) {
		code = TCL_OK;
		break;
	    }
	}
    }
    if (code != TCL_OK) {
	/*
	 * The package 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);
	code = TCL_ERROR;
	goto done;
    }


    /*





     * 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
     * the interpreter is a safe one, pkgPtr->safeUnloadProc must be non-NULL.
     */








    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",
		    NULL);






















	    code = TCL_ERROR;
	    goto done;
	}

	unloadProc = pkgPtr->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;
    }



    /*
     * We are ready to unload the package. 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.
     */




    code = TCL_UNLOAD_DETACH_FROM_INTERPRETER;
    if (!keepLibrary) {
	Tcl_MutexLock(&packageMutex);
	trustedRefCount = pkgPtr->interpRefCount;
	safeRefCount = pkgPtr->safeInterpRefCount;
	Tcl_MutexUnlock(&packageMutex);

	if (Tcl_IsSafe(target)) {
	    safeRefCount--;
	} else {
	    trustedRefCount--;
	}

	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;
    }


    /*


     * The unload function executed fine. Examine the reference count to see






     * if we unload the DLL.


















     */

    Tcl_MutexLock(&packageMutex);
    if (Tcl_IsSafe(target)) {
	pkgPtr->safeInterpRefCount--;

	/*
	 * Do not let counter get negative.
	 */

	if (pkgPtr->safeInterpRefCount < 0) {
	    pkgPtr->safeInterpRefCount = 0;
	}
    } else {
	pkgPtr->interpRefCount--;

	/*
	 * Do not let counter get negative.
	 */

	if (pkgPtr->interpRefCount < 0) {
	    pkgPtr->interpRefCount = 0;
	}
    }
    trustedRefCount = pkgPtr->interpRefCount;
    safeRefCount = pkgPtr->safeInterpRefCount;
    Tcl_MutexUnlock(&packageMutex);

    code = TCL_OK;
    if (pkgPtr->safeInterpRefCount <= 0 && pkgPtr->interpRefCount <= 0
	    && !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) {
		/*
		 * Remove this library from the loaded library cache.
		 */

		defaultPtr = pkgPtr;
		if (defaultPtr == firstPackagePtr) {
		    firstPackagePtr = pkgPtr->nextPtr;
		} else {
		    for (pkgPtr = firstPackagePtr; pkgPtr != NULL;
			    pkgPtr = pkgPtr->nextPtr) {
			if (pkgPtr->nextPtr == defaultPtr) {
			    pkgPtr->nextPtr = defaultPtr->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(defaultPtr->packageName);
		Tcl_Free(defaultPtr);
		Tcl_Free(ipPtr);
		Tcl_MutexUnlock(&packageMutex);
	    } 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 --
 *
 *	This function is invoked to indicate that a particular package has
 *	been linked statically with an application.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Once this function completes, the package 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
				 * already been loaded into the given
				 * interpreter by calling the appropriate init
				 * proc. */
    const char *pkgName,	/* Name of package (must be properly
				 * capitalized: first letter upper case,
				 * others lower case). */
    Tcl_PackageInitProc *initProc,
				/* Function to call to incorporate this
				 * package into a trusted interpreter. */
    Tcl_PackageInitProc *safeInitProc)
				/* Function to call to incorporate this
				 * package into a safe interpreter (one that
				 * will execute untrusted scripts). NULL means
				 * the package can't be used in safe
				 * interpreters. */
{
    LoadedPackage *pkgPtr;
    InterpPackage *ipPtr, *ipFirstPtr;

    /*
     * Check to see if someone else has already reported this package 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)) {
	    break;
	}
    }
    Tcl_MutexUnlock(&packageMutex);

    /*
     * If the package 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 (interp != NULL) {

	/*
	 * If we're loading the package into an interpreter, determine whether
	 * it's already loaded.
	 */

	ipFirstPtr = (InterpPackage *)Tcl_GetAssocData(interp, "tclLoad", NULL);
	for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    if (ipPtr->pkgPtr == pkgPtr) {
		return;
	    }
	}

	/*
	 * Package isn't loaded in the current interp yet. Mark it as now being
	 * loaded.
	 */

	ipPtr = (InterpPackage *)Tcl_Alloc(sizeof(InterpPackage));
	ipPtr->pkgPtr = pkgPtr;
	ipPtr->nextPtr = ipFirstPtr;
	Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc, ipPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetLoadedPackages, TclGetLoadedPackagesEx --
 *
 *	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.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclGetLoadedPackages(
    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.
				 */
{
    Tcl_Interp *target;
    LoadedPackage *pkgPtr;
    InterpPackage *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_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewListObj(2, pkgDesc));
	}
	Tcl_MutexUnlock(&packageMutex);
	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);

    /*
     * Return information about all of the available packages.
     */
    if (packageName) {
	resultObj = NULL;

	for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    pkgPtr = ipPtr->pkgPtr;

	    if (!strcmp(packageName, pkgPtr->packageName)) {
		resultObj = Tcl_NewStringObj(pkgPtr->fileName, -1);
		break;
	    }
	}

	if (resultObj) {
	    Tcl_SetObjResult(interp, resultObj);
	}
	return TCL_OK;
    }

    /*
     * Return information about only the packages 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);
	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
 *	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.
 *
 *----------------------------------------------------------------------
 */

static void
LoadCleanupProc(
    ClientData clientData,	/* Pointer to first InterpPackage structure
				 * for interp. */
    TCL_UNUSED(Tcl_Interp *))
{
    InterpPackage *ipPtr, *nextPtr;


    ipPtr = (InterpPackage *)clientData;
    while (ipPtr != NULL) {
	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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is freed.
 *
 *----------------------------------------------------------------------
 */

void
TclFinalizeLoad(void)
{
    LoadedPackage *pkgPtr;

    /*
     * No synchronization here because there should just be one thread alive
     * at this point. Logically, packageMutex 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;

#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);
	}
#endif

	Tcl_Free(pkgPtr->fileName);
	Tcl_Free(pkgPtr->packageName);
	Tcl_Free(pkgPtr);
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|














|







|


|

|
|
|


|

|

|





|













|
|

|
|
|
|


|

<
|


|


|
|

|
<
<

|





|

|
|

<
<
<





|


|



|
|

|



|







|





|
|




|
|

|







|






|




>
|
>
>
>
>
>
|
>
>
>
|
|
|
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
|
|
>
>
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
|

|
>
|
|
|
|
|
|
|
|
>
|


>
>

|








>
>
>
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
>
>
>





>

>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|

|





|
|


|





|
|


|
|
|


|
|












|
|
|




|
|
|

|
|
|
|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
|
|















<
<
<
<
<
<






|

|






|






|
|



|
<
<
|

|
|

|

|


|
|


|



|
|
|
|
|



|


|



|
|
|
|
|
|
|
|
|
>
>
|
|
|
|





|



|

|





|



|
|








|









|








|
<
<
<
<
<
<
<
<
<
<
<
<






|
|



|
|




|
|
|
|
|



|








|


|

|



|

|
|











|





|
|
|











|







|






|

|

|
>

<
|
|
|
>
>
|
>









|













|



|




|
|
|









|
|



|
|
|










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
		 * must clear the error.
		 */

		Tcl_ResetResult(interp);
		break;
	    }
	}
	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 ?prefix? ?interp?");
	return TCL_ERROR;
    }
    if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
	return TCL_ERROR;
    }

    fullFileName = TclGetString(objv[i]);
    Tcl_DStringInit(&pfx);
    Tcl_DStringInit(&tmp);

    prefix = NULL;
    if (objc - i >= 2) {
	prefix = TclGetString(objv[i+1]);
	if (prefix[0] == '\0') {
	    prefix = NULL;
	}
    }
    if ((fullFileName[0] == 0) && (prefix == NULL)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"must specify either file name or prefix", -1));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "NOLIBRARY",
		(char *)NULL);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * 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 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 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(&libraryMutex);


    for (libraryPtr = firstLibraryPtr; libraryPtr != NULL; libraryPtr = libraryPtr->nextPtr) {
	int namesMatch, filesMatch;

	if (prefix == NULL) {
	    namesMatch = 0;
	} else {
	    TclDStringClear(&pfx);
	    Tcl_DStringAppend(&pfx, prefix, -1);
	    TclDStringClear(&tmp);
	    Tcl_DStringAppend(&tmp, libraryPtr->prefix, -1);


	    if (strcmp(Tcl_DStringValue(&tmp),
		    Tcl_DStringValue(&pfx)) == 0) {
		namesMatch = 1;
	    } else {
		namesMatch = 0;
	    }
	}
	TclDStringClear(&pfx);

	filesMatch = (strcmp(libraryPtr->fileName, fullFileName) == 0);
	if (filesMatch && (namesMatch || (prefix == NULL))) {
	    break;



	}
	if (filesMatch && !namesMatch && (fullFileName[0] != 0)) {
	    break;
	}
    }
    Tcl_MutexUnlock(&libraryMutex);
    if (fullFileName[0] == 0) {
	/*
	 * It's an error to try unload a static library.
	 */

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"library with prefix \"%s\" is loaded statically and cannot be unloaded",
		prefix));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "UNLOAD", "STATIC",
		(char *)NULL);
	code = TCL_ERROR;
	goto done;
    }
    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",
		(char *)NULL);
	code = TCL_ERROR;
	goto done;
    }

    /*
     * 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 (libraryPtr != NULL) {
	ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
	for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    if (ipPtr->libraryPtr == libraryPtr) {
		code = TCL_OK;
		break;
	    }
	}
    }
    if (code != TCL_OK) {
	/*
	 * 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",
		(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;
}


/*
 *----------------------------------------------------------------------
 *
 * UnloadLibrary --
 *
 *	Unloads a library from an interpreter, and also from the process if it
 *	is unloadable, i.e. if it provides an "unload" function.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See description.
 *
 *----------------------------------------------------------------------
 */
static int
UnloadLibrary(
	Tcl_Interp *interp,
	Tcl_Interp *target,
	LoadedLibrary *libraryPtr,
	int keepLibrary,
	const char *fullFileName,
	int interpExiting

)
{
    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 (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 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(&libraryMutex);
	    trustedRefCount = libraryPtr->interpRefCount;
	    safeRefCount = libraryPtr->safeInterpRefCount;
	    Tcl_MutexUnlock(&libraryMutex);

	    if (Tcl_IsSafe(target)) {
		safeRefCount--;
	    } else {
		trustedRefCount--;
	    }

	    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.
     */

    ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);
    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(&libraryMutex);
    if (Tcl_IsSafe(target)) {
	libraryPtr->safeInterpRefCount--;

	/*
	 * Do not let counter get negative.
	 */

	if (libraryPtr->safeInterpRefCount < 0) {
	    libraryPtr->safeInterpRefCount = 0;
	}
    } else {
	libraryPtr->interpRefCount--;

	/*
	 * Do not let counter get negative.
	 */

	if (libraryPtr->interpRefCount < 0) {
	    libraryPtr->interpRefCount = 0;
	}
    }
    trustedRefCount = libraryPtr->interpRefCount;
    safeRefCount = libraryPtr->safeInterpRefCount;
    Tcl_MutexUnlock(&libraryMutex);

    code = TCL_OK;
    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 (!IsStatic(libraryPtr)) {
	    Tcl_MutexLock(&libraryMutex);
	    if (Tcl_FSUnloadFile(interp, libraryPtr->loadHandle) == TCL_OK) {
		/*
		 * Remove this library from the loaded library cache.
		 */

		iterLibraryPtr = libraryPtr;
		if (iterLibraryPtr == firstLibraryPtr) {
		    firstLibraryPtr = libraryPtr->nextPtr;
		} else {
		    for (libraryPtr = firstLibraryPtr; libraryPtr != NULL;
			    libraryPtr = libraryPtr->nextPtr) {
			if (libraryPtr->nextPtr == iterLibraryPtr) {
			    libraryPtr->nextPtr = iterLibraryPtr->nextPtr;
			    break;
			}
		    }
		}






















		Tcl_Free(iterLibraryPtr->fileName);

		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:






    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_StaticLibrary --
 *
 *	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 library becomes loadable via the
 *	"load" command with an empty file name.
 *
 *----------------------------------------------------------------------
 */

void
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 *prefix,	/* Prefix. */


    Tcl_LibraryInitProc *initProc,
				/* Function to call to incorporate this
				 * library into a trusted interpreter. */
    Tcl_LibraryInitProc *safeInitProc)
				/* Function to call to incorporate this
				 * library into a safe interpreter (one that
				 * will execute untrusted scripts). NULL means
				 * the library can't be used in safe
				 * interpreters. */
{
    LoadedLibrary *libraryPtr;
    InterpLibrary *ipPtr, *ipFirstPtr;

    /*
     * Check to see if someone else has already reported this library as
     * statically loaded in the process.
     */

    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(&libraryMutex);

    /*
     * If the library is not yet recorded as being loaded statically, add it
     * to the list now.
     */

    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 library into an interpreter, determine whether
	 * it's already loaded.
	 */

	ipFirstPtr = (InterpLibrary *)Tcl_GetAssocData(interp, "tclLoad", NULL);
	for (ipPtr = ipFirstPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    if (ipPtr->libraryPtr == libraryPtr) {
		return;
	    }
	}

	/*
	 * Library isn't loaded in the current interp yet. Mark it as now being
	 * loaded.
	 */

	ipPtr = (InterpLibrary *)Tcl_Alloc(sizeof(InterpLibrary));
	ipPtr->libraryPtr = libraryPtr;
	ipPtr->nextPtr = ipFirstPtr;
	Tcl_SetAssocData(interp, "tclLoad", LoadCleanupProc, ipPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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 prefix of the library in that file.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
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. */
    const char *prefix)	/* Prefix or NULL. If NULL, return info
				 * for all prefixes.
				 */
{
    Tcl_Interp *target;
    LoadedLibrary *libraryPtr;
    InterpLibrary *ipPtr;
    Tcl_Obj *resultObj, *pkgDesc[2];

    if (targetName == NULL) {
	TclNewObj(resultObj);
	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(&libraryMutex);
	Tcl_SetObjResult(interp, resultObj);
	return TCL_OK;
    }

    target = Tcl_GetChild(interp, targetName);
    if (target == NULL) {
	return TCL_ERROR;
    }
    ipPtr = (InterpLibrary *)Tcl_GetAssocData(target, "tclLoad", NULL);

    /*
     * Return information about all of the available libraries.
     */
    if (prefix) {
	resultObj = NULL;

	for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	    libraryPtr = ipPtr->libraryPtr;

	    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 libraries that are loaded in a given
     * interpreter.
     */

    TclNewObj(resultObj);
    for (; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
	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 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 InterpLibrary functions for interp get deleted.
 *
 *----------------------------------------------------------------------
 */

static void
LoadCleanupProc(
    TCL_UNUSED(void *),	/* Pointer to first InterpLibrary structure
				 * for interp. */
    Tcl_Interp *interp)
{
    InterpLibrary *ipPtr;
    LoadedLibrary *libraryPtr;


    while (1) {
	ipPtr = (InterpLibrary *)Tcl_GetAssocData(interp, "tclLoad", NULL);
	if (ipPtr == NULL) {
	    break;
	}
	libraryPtr = ipPtr->libraryPtr;
	UnloadLibrary(interp, interp, libraryPtr, 0 ,"", 1);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclFinalizeLoad --
 *
 *	This function is invoked just before the application exits. It frees
 *	all of the LoadedLibrary structures.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Memory is freed.
 *
 *----------------------------------------------------------------------
 */

void
TclFinalizeLoad(void)
{
    LoadedLibrary *libraryPtr;

    /*
     * No synchronization here because there should just be one thread alive
     * 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 (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 (!IsStatic(libraryPtr)) {
	    Tcl_FSUnloadFile(NULL, libraryPtr->loadHandle);
	}
#endif

	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
/*
 * 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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|







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 © 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
    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 */
{
    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,
				/* Dummy: unused by this implementation */
    int flags)
				/* 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;
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<











|
|







|
|
|
|
|
<
|
<







48
49
50
51
52
53
54






























55
56
57
58
59
60
61
62
63
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;
}































/*
 * 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_UNUSED(Tcl_Interp *),
    TCL_UNUSED(int))
{
    return NULL;
}

MODULE_SCOPE int
TclpLoadMemory(
    Tcl_Interp *interp,		/* Used for error reporting. */
    TCL_UNUSED(void *),
    TCL_UNUSED(int),
    TCL_UNUSED(int),
    TCL_UNUSED(Tcl_LoadHandle *),
    TCL_UNUSED(Tcl_FSUnloadFileProc **),

    TCL_UNUSED(int))

{
    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
/*
 * 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.
 *
 * 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	"% "


/*
 * 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 *
NewNativeObj(
    TCHAR *string)
{
    Tcl_DString ds;

#ifdef UNICODE
    Tcl_DStringInit(&ds);
    Tcl_WCharToUtfDString(string, -1, &ds);
#else
    Tcl_ExternalToUtfDString(NULL, (char *)string, -1, &ds);
#endif
    return TclDStringToObj(&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,










|
|
|

















|
>














|









|

|








<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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 © 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.
 */

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 inline Tcl_Obj *
NewNativeObj(
    TCHAR *string)
{
    Tcl_DString ds;

#ifdef UNICODE
    Tcl_DStringInit(&ds);
    Tcl_WCharToUtfDString(string, -1, &ds);
#else
    (void)Tcl_ExternalToUtfDString(NULL, (char *)string, -1, &ds);
#endif
    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).
 */






/*
 * 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

/*
 * 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);

#if !defined(_WIN32) || defined(UNICODE) && !defined(TCL_ASCII_MAIN)
static Tcl_ThreadDataKey dataKey;

/*
 *----------------------------------------------------------------------
 *







|
|







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(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
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetStartupScript(
    Tcl_Obj *path,		/* Filesystem path of startup script file */
    const char *encoding)	/* Encoding of the data in that file */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    Tcl_Obj *newEncoding = NULL;

    if (encoding != NULL) {
	newEncoding = Tcl_NewStringObj(encoding, -1);

    }




    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;
    if (tsdPtr->encoding != NULL) {
	Tcl_IncrRefCount(tsdPtr->encoding);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetStartupScript --
 *







|


|

|
|
>


>
>
>




<
<
<




|
<
<
<







132
133
134
135
136
137
138
139
140
141
142
143
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 *encodingName)	/* Encoding of the data in that file */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    Tcl_Obj *encodingObj = NULL;

    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->encoding != NULL) {
	Tcl_DecrRefCount(tsdPtr->encoding);
    }
    tsdPtr->encoding = encodingObj;



}

/*
 *----------------------------------------------------------------------
 *
 * 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
				 * (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;
	} else {
	    *encodingPtr = TclGetString(tsdPtr->encoding);
	}
    }
    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.

 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Depends on what's in the rc script.
 *







|
|

|











|
>







186
187
188
189
190
191
192
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 = Tcl_GetString(tsdPtr->encoding);
	} else {
	    *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. 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
    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) {
	    /*
	     * 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));


			Tcl_WriteChars(chan, "\n", 1);
		    }
		}
	    }
	}
	Tcl_DStringFree(&temp);
    }







|
<
<
<
<
<
<










|
>
>







228
229
230
231
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) {






	    /*
	     * 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) {
			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
 *	interpreted.
 *
 *----------------------------------------------------------------------
 */

TCL_NORETURN void
Tcl_MainEx(
    int 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_Obj *path, *resultPtr, *argvPtr, *appName;
    const char *encodingName = NULL;
    int code, exitCode = 0;
    Tcl_MainLoopProc *mainLoopProc;
    Tcl_Channel chan;
    InteractiveState is;

    TclpSetInitialEncodings();




    TclpFindExecutable((const char *)argv[0]);


    Tcl_InitMemory(interp);

    is.interp = interp;
    is.prompt = PROMPT_START;
    TclNewObj(is.commandPtr);








|







>








>
>
>
>
|
>







272
273
274
275
276
277
278
279
280
281
282
283
284
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(
    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]);	/* 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
	/*
	 * Check whether first 3 args (argv[1] - argv[3]) look like
	 *  -encoding ENCODING FILENAME
	 * or like
	 *  FILENAME
	 */


	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_DecrRefCount(value);
	    argc -= 3;
	    argv += 3;
	} else if ((argc > 1) && ('-' != argv[1][0])) {
	    Tcl_SetStartupScript(NewNativeObj(argv[1]), NULL);
	    argc--;
	    argv++;
	}
    }

    path = Tcl_GetStartupScript(&encodingName);
    if (path == NULL) {


	appName = NewNativeObj(argv[0]);
    } else {
	appName = path;
    }
    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_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);

    /*
     * 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));


	    Tcl_WriteChars(chan, "\n", 1);
	}
    }
    if (Tcl_InterpDeleted(interp)) {
	goto done;
    }
    if (Tcl_LimitExceeded(interp)) {







>
|



|


|
|


|




|
>
>


|


<
<





|









|











|
>
>







316
317
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]))
		&& ('-' != argv[3][0])) {
	    Tcl_Obj *value = NewNativeObj(argv[2]);
	    Tcl_SetStartupScript(NewNativeObj(argv[3]),
		    Tcl_GetString(value));
	    Tcl_DecrRefCount(value);
	    argc -= 3;
	    i += 3;
	} else if ((argc >= 1) && ('-' != argv[1][0])) {
	    Tcl_SetStartupScript(NewNativeObj(argv[1]), NULL);
	    argc--;
	    i++;
	}
    }

    path = Tcl_GetStartupScript(&encodingName);
    if (path != NULL) {
	appName = path;
    } else if (argv[0]) {
	appName = NewNativeObj(argv[0]);
    } else {
	appName = Tcl_NewStringObj("tclsh", -1);
    }
    Tcl_SetVar2Ex(interp, "argv0", NULL, appName, TCL_GLOBAL_ONLY);



    Tcl_SetVar2Ex(interp, "argc", NULL, Tcl_NewWideIntObj(argc), TCL_GLOBAL_ONLY);

    argvPtr = Tcl_NewListObj(0, NULL);
    while (argc--) {
	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_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);
	    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)) {
410
411
412
413
414
415
416
417


418
419
420
421
422
423
424

		TclNewLiteralStringObj(keyPtr, "-errorinfo");
		Tcl_IncrRefCount(keyPtr);
		Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr);
		Tcl_DecrRefCount(keyPtr);

		if (valuePtr) {
		    Tcl_WriteObj(chan, valuePtr);


		}
		Tcl_WriteChars(chan, "\n", 1);
		Tcl_DecrRefCount(options);
	    }
	    exitCode = 1;
	}
	goto done;







|
>
>







410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426

		TclNewLiteralStringObj(keyPtr, "-errorinfo");
		Tcl_IncrRefCount(keyPtr);
		Tcl_DictObjGet(NULL, options, keyPtr, &valuePtr);
		Tcl_DecrRefCount(keyPtr);

		if (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
     */

    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;

	    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 (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.







|




















|







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
     */

    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) {
	    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 < 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
	    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);
	    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));


		    Tcl_WriteChars(chan, "\n", 1);
		}
	    } else if (is.tty) {
		resultPtr = Tcl_GetObjResult(interp);
		Tcl_IncrRefCount(resultPtr);
		(void)TclGetStringFromObj(resultPtr, &length);
		chan = Tcl_GetStdChannel(TCL_STDOUT);
		if ((length > 0) && chan) {
		    Tcl_WriteObj(chan, resultPtr);


		    Tcl_WriteChars(chan, "\n", 1);
		}
		Tcl_DecrRefCount(resultPtr);
	    }
	} else {	/* (mainLoopProc != NULL) */
	    /*
	     * If a main loop has been defined while running interactively, we







|










|
>
>





|


|
>
>







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
	    is.prompt = PROMPT_START;

	    /*
	     * The final newline is syntactically redundant, and causes some
	     * error messages troubles deeper in, so lop it back off.
	     */

	    (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) {
			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)Tcl_GetStringFromObj(resultPtr, &length);
		chan = Tcl_GetStdChannel(TCL_STDOUT);
		if ((length > 0) && chan) {
		    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
 *	Could be almost arbitrary, depending on the command that's typed.
 *
 *----------------------------------------------------------------------
 */

static void
StdinProc(
    ClientData clientData,	/* The state of interactive cmd line */
    TCL_UNUSED(int) /*mask*/)
{
    int code;
    size_t 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 (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







|



|











|







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
 *	Could be almost arbitrary, depending on the command that's typed.
 *
 *----------------------------------------------------------------------
 */

static void
StdinProc(
    void *clientData,	/* The state of interactive cmd line */
    TCL_UNUSED(int) /*mask*/)
{
    int code;
    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 < 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
    }
    Tcl_AppendToObj(commandPtr, "\n", 1);
    if (!TclObjCommandComplete(commandPtr)) {
	isPtr->prompt = PROMPT_CONTINUE;
	goto prompt;
    }
    isPtr->prompt = PROMPT_START;
    (void)TclGetStringFromObj(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.







|







779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
    }
    Tcl_AppendToObj(commandPtr, "\n", 1);
    if (!TclObjCommandComplete(commandPtr)) {
	isPtr->prompt = PROMPT_CONTINUE;
	goto prompt;
    }
    isPtr->prompt = PROMPT_START;
    (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
    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));


	    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);
	if ((length > 0) && (chan != NULL)) {
	    Tcl_WriteObj(chan, resultPtr);


	    Tcl_WriteChars(chan, "\n", 1);
	}
	Tcl_DecrRefCount(resultPtr);
    }

    /*
     * If a tty stdin is still around, output a prompt.







|
>
>







|

|
>
>







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
    if (chan != NULL) {
	Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc, isPtr);
    }
    if (code != TCL_OK) {
	chan = Tcl_GetStdChannel(TCL_STDERR);

	if (chan != NULL) {
	    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)Tcl_GetStringFromObj(resultPtr, &length);
	if ((length > 0) && (chan != NULL)) {
	    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
    }
    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));
	    }
	}
    } 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));


		Tcl_WriteChars(chan, "\n", 1);
	    }
	    goto defaultPrompt;
	}
    }

    chan = Tcl_GetStdChannel(TCL_STDOUT);







|









|
>
>







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
    }
    if (promptCmdPtr == NULL) {
    defaultPrompt:
	if (isPtr->prompt == PROMPT_START) {
	    chan = Tcl_GetStdChannel(TCL_STDOUT);
	    if (chan != NULL) {
		Tcl_WriteChars(chan, 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) {
		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
 *	startup script storage at exit.
 *
 *----------------------------------------------------------------------
 */

static void
FreeMainInterp(
    ClientData clientData)
{
    Tcl_Interp *interp = (Tcl_Interp *)clientData;

    /*if (TclInExit()) return;*/

    if (!Tcl_InterpDeleted(interp)) {
	Tcl_DeleteInterp(interp);







|







917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
 *	startup script storage at exit.
 *
 *----------------------------------------------------------------------
 */

static void
FreeMainInterp(
    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
/*
 * 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.
 * Contributions from Don Porter, NIST, 2007. (not subject to US copyright)
 *
 * Originally implemented by
 *   Michael J. McLennan
 *   Bell Labs Innovations for Lucent Technologies
 *   [email protected]
 *









|
|
|
|
|







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 © 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
 *   [email protected]
 *
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
				 * becomes zero. */
} ResolvedNsName;

/*
 * Declarations for functions local to this file:
 */

static void		DeleteImportedCmd(ClientData 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,
			    const char *name1, const char *name2, int flags);
static char *		ErrorInfoRead(ClientData clientData,Tcl_Interp *interp,
			    const char *name1, const char *name2, int flags);
static char *		EstablishErrorCodeTraces(ClientData clientData,
			    Tcl_Interp *interp, const char *name1,
			    const char *name2, int flags);
static char *		EstablishErrorInfoTraces(ClientData 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 Tcl_ObjCmdProc	NamespaceChildrenCmd;
static Tcl_ObjCmdProc	NamespaceCodeCmd;
static Tcl_ObjCmdProc	NamespaceCurrentCmd;
static Tcl_ObjCmdProc	NamespaceDeleteCmd;
static Tcl_ObjCmdProc	NamespaceEvalCmd;
static Tcl_ObjCmdProc	NRNamespaceEvalCmd;







|





|

|

|


|





|







67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
				 * becomes zero. */
} ResolvedNsName;

/*
 * Declarations for functions local to this file:
 */

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(void *clientData,Tcl_Interp *interp,
			    const char *name1, const char *name2, int flags);
static char *		ErrorInfoRead(void *clientData,Tcl_Interp *interp,
			    const char *name1, const char *name2, int flags);
static char *		EstablishErrorCodeTraces(void *clientData,
			    Tcl_Interp *interp, const char *name1,
			    const char *name2, int flags);
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(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;
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
 */

static const Tcl_ObjType nsNameType = {
    "nsName",			/* the type's name */
    FreeNsNameInternalRep,	/* freeIntRepProc */
    DupNsNameInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetNsNameFromAny		/* setFromAnyProc */

};

#define NsNameSetIntRep(objPtr, nnPtr)					\
    do {								\
	Tcl_ObjIntRep ir;						\
	(nnPtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (nnPtr);					\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &nsNameType, &ir);			\
    } while (0)

#define NsNameGetIntRep(objPtr, nnPtr)					\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((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.
 */







|
>


|

|



|


|

|
|







126
127
128
129
130
131
132
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 const Tcl_ObjType nsNameType = {
    "nsName",			/* the type's name */
    FreeNsNameInternalRep,	/* freeIntRepProc */
    DupNsNameInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetNsNameFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V0
};

#define NsNameSetInternalRep(objPtr, nnPtr)					\
    do {								\
	Tcl_ObjInternalRep ir;						\
	(nnPtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (nnPtr);					\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreInternalRep((objPtr), &nsNameType, &ir);			\
    } while (0)

#define NsNameGetInternalRep(objPtr, nnPtr)					\
    do {								\
	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.
 */
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    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
	 * 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);
    } else {
	framePtr->level = 0;
    }
    framePtr->procPtr = NULL;		/* no called procedure */
    framePtr->varTablePtr = NULL;	/* and no local variables */
    framePtr->numCompiledLocals = 0;
    framePtr->compiledLocals = NULL;







|



















|







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
    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_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 + 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
    /*
     * 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))
	    && (nsPtr->flags & NS_DYING)) {
	Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr);
    }
    framePtr->nsPtr = NULL;

    if (framePtr->tailcallPtr) {


	TclSetTailcall(interp, framePtr->tailcallPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *







|






>
>







406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
    /*
     * 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 <= (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);
    }
}

/*
 *----------------------------------------------------------------------
 *
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
 *	Read and unset traces are established on ::errorCode.
 *
 *----------------------------------------------------------------------
 */

static char *
EstablishErrorCodeTraces(
    TCL_UNUSED(ClientData),
    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);







|







491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
 *	Read and unset traces are established on ::errorCode.
 *
 *----------------------------------------------------------------------
 */

static char *
EstablishErrorCodeTraces(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
ErrorCodeRead(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    TCL_UNUSED(const char *) /*name1*/,
    TCL_UNUSED(const char *) /*name2*/,
    TCL_UNUSED(int) /*flags*/)
{
    Interp *iPtr = (Interp *) interp;








|







523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
ErrorCodeRead(
    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
 *	Read and unset traces are established on ::errorInfo.
 *
 *----------------------------------------------------------------------
 */

static char *
EstablishErrorInfoTraces(
    TCL_UNUSED(ClientData),
    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);







|







565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
 *	Read and unset traces are established on ::errorInfo.
 *
 *----------------------------------------------------------------------
 */

static char *
EstablishErrorInfoTraces(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
ErrorInfoRead(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    TCL_UNUSED(const char *) /*name1*/,
    TCL_UNUSED(const char *) /*name2*/,
    TCL_UNUSED(int) /*flags*/)
{
    Interp *iPtr = (Interp *) interp;








|







597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
 *	None.
 *
 *----------------------------------------------------------------------
 */

static char *
ErrorInfoRead(
    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
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. */
    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;







|







649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
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. */
    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
     * 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));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NAMESPACE",
		"CREATEGLOBAL", NULL);
	Tcl_DStringFree(&tmpBuffer);
	return NULL;
    }

    /*
     * Find the parent for the new namespace.
     */







|

|







711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
     * 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));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NAMESPACE",
		"CREATEGLOBAL", (char *)NULL);
	Tcl_DStringFree(&tmpBuffer);
	return NULL;
    }

    /*
     * Find the parent for the new namespace.
     */
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
	parentPtr->childTablePtr != NULL &&
	Tcl_FindHashEntry(parentPtr->childTablePtr, simpleName) != NULL
#endif
    ) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't create namespace \"%s\": already exists", name));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NAMESPACE",
		"CREATEEXISTING", NULL);
	Tcl_DStringFree(&tmpBuffer);
	return NULL;
    }

    /*
     * Create the new namespace and root it in its parent. Increment the count
     * of namespaces created.







|







752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
	parentPtr->childTablePtr != NULL &&
	Tcl_FindHashEntry(parentPtr->childTablePtr, simpleName) != NULL
#endif
    ) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't create namespace \"%s\": already exists", name));
	Tcl_SetErrorCode(interp, "TCL", "OPERATION", "NAMESPACE",
		"CREATEEXISTING", (char *)NULL);
	Tcl_DStringFree(&tmpBuffer);
	return NULL;
    }

    /*
     * Create the new namespace and root it in its parent. Increment the count
     * of namespaces created.
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

    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.
     */

    if (nsPtr->activationCount > (unsigned)(nsPtr == globalNsPtr)) {
	nsPtr->flags |= NS_DYING;
	if (nsPtr->parentPtr != NULL) {
	    entryPtr = Tcl_FindHashEntry(
		    TclGetNamespaceChildTable((Tcl_Namespace *)
			    nsPtr->parentPtr), nsPtr->name);
	    if (entryPtr != NULL) {
		Tcl_DeleteHashEntry(entryPtr);
	    }
	}
	nsPtr->parentPtr = NULL;
    } else if (!(nsPtr->flags & NS_KILLED)) {
	/*
	 * 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
	 * recursive calls here - if the namespace is really in the process of
	 * being deleted, ignore any second call.
	 */

	nsPtr->flags |= (NS_DYING|NS_KILLED);

	TclTeardownNamespace(nsPtr);

	if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
	    /*
	     * If this is the global namespace, then it may have residual
	     * "errorInfo" and "errorCode" variables for errors that occurred







|
|
>
|
|
|
|
|
|
|
|
|
|
|
|


|










|



|




|







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

    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):  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 > (nsPtr == globalNsPtr)) {
	nsPtr->flags |= NS_DYING;
	if (nsPtr->parentPtr != NULL) {
	    entryPtr = Tcl_FindHashEntry(
		    TclGetNamespaceChildTable((Tcl_Namespace *)
			    nsPtr->parentPtr), nsPtr->name);
	    if (entryPtr != NULL) {
		Tcl_DeleteHashEntry(entryPtr);
	    }
	}
	nsPtr->parentPtr = NULL;
    } 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_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_TEARDOWN);

	TclTeardownNamespace(nsPtr);

	if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
	    /*
	     * If this is the global namespace, then it may have residual
	     * "errorInfo" and "errorCode" variables for errors that occurred
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
	    EstablishErrorCodeTraces(NULL, nsPtr->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);
	}
    }
    TclNsDecrRefCount(nsPtr);
}

int
TclNamespaceDeleted(
    Namespace *nsPtr)
{
    return (nsPtr->flags & NS_DYING) ? 1 : 0;
}















































































/*
 *----------------------------------------------------------------------
 *
 * TclTeardownNamespace --
 *
 *	Used internally to dismantle and unlink a namespace when it is







|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    EstablishErrorCodeTraces(NULL, nsPtr->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_TEARDOWN);
	}
    }
    TclNsDecrRefCount(nsPtr);
}

int
TclNamespaceDeleted(
    Namespace *nsPtr)
{
    return (nsPtr->flags & NS_DYING) ? 1 : 0;
}

void
TclDeleteNamespaceChildren(
    Namespace *nsPtr	/* Namespace whose children to delete */
)
{
    Interp *iPtr = (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 proplery 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.
     */

#ifndef BREAK_NAMESPACE_COMPAT
    unchecked = (nsPtr->childTable.numEntries > 0);
    while (nsPtr->childTable.numEntries > 0 && unchecked) {
	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++;
	}
	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((Tcl_Interp *) iPtr, children);
    }
#else
    if (nsPtr->childTablePtr != NULL) {
	unchecked = (nsPtr->childTable.numEntries > 0);
	while (nsPtr->childTable.numEntries > 0 && unchecked) {
	    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] = (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((Tcl_Interp *) iPtr, children);
	}
    }
#endif
}

/*
 *----------------------------------------------------------------------
 *
 * TclTeardownNamespace --
 *
 *	Used internally to dismantle and unlink a namespace when it is
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
TclTeardownNamespace(
    Namespace *nsPtr)	/* Points to the namespace to be dismantled
				 * and unlinked from its parent. */
{
    Interp *iPtr = (Interp *) nsPtr->interp;
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    size_t 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,
		sizeof(Command *) * length);

	i = 0;
	for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
		entryPtr != NULL;
		entryPtr = Tcl_NextHashEntry(&search)) {







|




















|







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
TclTeardownNamespace(
    Namespace *nsPtr)	/* Points to the namespace to be dismantled
				 * and unlinked from its parent. */
{
    Interp *iPtr = (Interp *) nsPtr->interp;
    Tcl_HashEntry *entryPtr;
    Tcl_HashSearch search;
    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) {
	Tcl_Size length = nsPtr->cmdTable.numEntries;
	Command **cmds = (Command **)TclStackAlloc((Tcl_Interp *) iPtr,
		sizeof(Command *) * length);

	i = 0;
	for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
		entryPtr != NULL;
		entryPtr = Tcl_NextHashEntry(&search)) {
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
	    }
	    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.
     *
     * 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++) {







<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1259
1260
1261
1262
1263
1264
1265








1266















































1267
1268
1269
1270
1271
1272
1273
	    }
	    nsPathPtr->nsPtr = NULL;
	    nsPathPtr = nsPathPtr->nextPtr;
	} while (nsPathPtr != NULL);
	nsPtr->commandPathSourceList = NULL;
    }









    TclDeleteNamespaceChildren(nsPtr);
















































    /*
     * Free the namespace's export pattern array.
     */

    if (nsPtr->exportArrayPtr != NULL) {
	for (i = 0;  i < nsPtr->numExportPatterns;  i++) {
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
				 * 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;

    /*
     * If the specified namespace is NULL, use the current namespace.
     */

    if (namespacePtr == NULL) {
	nsPtr = (Namespace *) currNsPtr;







|







1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
				 * list before appending. */
{
#define INIT_EXPORT_PATTERNS 5
    Namespace *nsPtr, *exportNsPtr, *dummyPtr;
    Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    const char *simplePattern;
    char *patternCpy;
    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
     */

    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);
	return TCL_ERROR;
    }

    /*
     * Make sure that we don't already have the pattern in the array
     */








|
|







1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
     */

    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", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Make sure that we don't already have the pattern in the array
     */

1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
    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;
    int result;

    /*
     * If the specified namespace is NULL, use the current namespace.
     */

    if (namespacePtr == NULL) {







|







1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
    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;
    Tcl_Size i;
    int result;

    /*
     * If the specified namespace is NULL, use the current namespace.
     */

    if (namespacePtr == NULL) {
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
    /*
     * 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);
	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);
	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);
	} 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);
	}
	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







|







|
|






|
|


|
|
|







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
    /*
     * 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", (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, (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", (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", (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
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
    Namespace *nsPtr,
    Tcl_HashEntry *hPtr,
    const char *cmdName,
    const char *pattern,
    Namespace *importNsPtr,
    int allowOverwrite)
{
    size_t 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.
     */








|







1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
    Namespace *nsPtr,
    Tcl_HashEntry *hPtr,
    const char *cmdName,
    const char *pattern,
    Namespace *importNsPtr,
    int allowOverwrite)
{
    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.
     */

1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
	    Command *linkCmd = cmdPtr;

	    while (linkCmd->deleteProc == DeleteImportedCmd) {
		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)));
		    Tcl_DStringFree(&ds);
		    Tcl_SetErrorCode(interp, "TCL", "IMPORT", "LOOP", NULL);
		    return TCL_ERROR;
		}
	    }
	}

	dataPtr = (ImportedCmdData *)Tcl_Alloc(sizeof(ImportedCmdData));
	importedCmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds),







|
|
|

|







1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
	    Command *linkCmd = cmdPtr;

	    while (linkCmd->deleteProc == DeleteImportedCmd) {
		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)));
		    Tcl_DStringFree(&ds);
		    Tcl_SetErrorCode(interp, "TCL", "IMPORT", "LOOP", (char *)NULL);
		    return TCL_ERROR;
		}
	    }
	}

	dataPtr = (ImportedCmdData *)Tcl_Alloc(sizeof(ImportedCmdData));
	importedCmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds),
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
		 * 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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|
|







1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
		 * 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", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
    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);
	return TCL_ERROR;
    }

    if (strcmp(pattern, simplePattern) == 0) {
	/*
	 * The pattern is simple. Delete any imported commands that match it.
	 */







|







1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
    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, (char *)NULL);
	return TCL_ERROR;
    }

    if (strcmp(pattern, simplePattern) == 0) {
	/*
	 * The pattern is simple. Delete any imported commands that match it.
	 */
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
 *	wrong, the result object is set to an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InvokeImportedNRCmd(
    ClientData 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;
    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
				 * 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);







|














|







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
 *	wrong, the result object is set to an error message.
 *
 *----------------------------------------------------------------------
 */

static int
InvokeImportedNRCmd(
    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;
    Command *realCmdPtr = dataPtr->realCmdPtr;

    TclSkipTailcall(interp);
    return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NOERR, realCmdPtr);
}

int
TclInvokeImportedCmd(
    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
 *	Removes the imported command from the real command's import list.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteImportedCmd(
    ClientData clientData)	/* Points to the imported command's
				 * ImportedCmdData structure. */
{
    ImportedCmdData *dataPtr = (ImportedCmdData *)clientData;
    Command *realCmdPtr = dataPtr->realCmdPtr;
    Command *selfPtr = dataPtr->selfPtr;
    ImportRef *refPtr, *prevPtr;








|







2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
 *	Removes the imported command from the real command's import list.
 *
 *----------------------------------------------------------------------
 */

static void
DeleteImportedCmd(
    void *clientData)	/* Points to the imported command's
				 * ImportedCmdData structure. */
{
    ImportedCmdData *dataPtr = (ImportedCmdData *)clientData;
    Command *realCmdPtr = dataPtr->realCmdPtr;
    Command *selfPtr = dataPtr->selfPtr;
    ImportRef *refPtr, *prevPtr;

2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
 *	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,
 *	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







|







2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
 *	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_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
				 * 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 *altNsPtr;
    Namespace *globalNsPtr = iPtr->globalNsPtr;
    const char *start, *end;
    const char *nsName;
    Tcl_HashEntry *entryPtr;
    Tcl_DString buffer;
    int len;







|







2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
				 * 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, *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
	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 == ':') {
	    start++;			/* Skip over a subsequent : */
	}
	nsPtr = globalNsPtr;
	if (*start == '\0') {		/* qualName is just two or more
					 * ":"s. */
	    *nsPtrPtr = globalNsPtr;
	    *altNsPtrPtr = NULL;
	    *actualCxtPtrPtr = globalNsPtr;
	    *simpleNamePtr = start;	/* Points to empty string. */
	    return TCL_OK;
	}







|
|
|



|







2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
	nsPtr = globalNsPtr;
    } else if (nsPtr == NULL) {
	nsPtr = iPtr->varFramePtr->nsPtr;
    }

    start = qualName;			/* Points to start of qualifying
					 * namespace. */
    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] == '\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
	 * 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) == ':')) {
		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)==':')) {
	    /*
	     * 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;

	    }
	} 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.
	 */

	if (nsPtr != NULL) {
#ifndef BREAK_NAMESPACE_COMPAT
	    entryPtr = Tcl_FindHashEntry(&nsPtr->childTable, nsName);
#else
	    if (nsPtr->childTablePtr == NULL) {







|









|









<
<

<
<
>



















|







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
	 * 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[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]=='\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 {


		*simpleNamePtr = start;


		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_CreateObjCommand that cannot fail.
	 */

	if (nsPtr != NULL) {
#ifndef BREAK_NAMESPACE_COMPAT
	    entryPtr = Tcl_FindHashEntry(&nsPtr->childTable, nsName);
#else
	    if (nsPtr->childTablePtr == NULL) {
2347
2348
2349
2350
2351
2352
2353


2354

2355

2356
2357
2358
2359
2360
2361
2362
		nsPtr = (Namespace *)
			Tcl_CreateNamespace(interp, nsName, NULL, NULL);
		TclPopStackFrame(interp);

		if (nsPtr == NULL) {
		    Tcl_Panic("Could not create namespace '%s'", nsName);
		}


	    } else {			/* Namespace not found and was not

					 * created. */

		nsPtr = NULL;
	    }
	}

	/*
	 * Look up the namespace qualifier in the alternate search path too.
	 */







>
>
|
>
|
>







2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
		nsPtr = (Namespace *)
			Tcl_CreateNamespace(interp, nsName, NULL, NULL);
		TclPopStackFrame(interp);

		if (nsPtr == NULL) {
		    Tcl_Panic("Could not create namespace '%s'", nsName);
		}
	    } else {
		/*
		 * 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.
	 */
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
	    } else {
		entryPtr = NULL;
	    }
#endif
	    if (entryPtr != NULL) {
		altNsPtr = (Namespace *)Tcl_GetHashValue(entryPtr);
	    } else {


		altNsPtr = NULL;
	    }
	}

	/*
	 * If both search paths have failed, return NULL results.
	 */

	if ((nsPtr == NULL) && (altNsPtr == NULL)) {






	    *nsPtrPtr = NULL;
	    *altNsPtrPtr = NULL;



	    *simpleNamePtr = NULL;
	    Tcl_DStringFree(&buffer);
	    return TCL_OK;

	}

	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)!=':')) {
	*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;
    }


    *nsPtrPtr = nsPtr;
    *altNsPtrPtr = altNsPtr;
    Tcl_DStringFree(&buffer);
    return TCL_OK;
}

/*







>
>









>
>
>
>
>
>
|
|
>
>
>

<
<
>










|


















>







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
	    } else {
		entryPtr = NULL;
	    }
#endif
	    if (entryPtr != NULL) {
		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
		 */
		nsPtr = lastNsPtr;
		altNsPtr = lastAltNsPtr;
		*simpleNamePtr = start;
		goto done;
	    }
	    *simpleNamePtr = NULL;


	    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]!=':')) {
	*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;
}

/*
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517

    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);
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *







|
|







2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556

    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, (char *)NULL);
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
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
    /*
     * Find the namespace(s) that contain the command.
     */

    cmdPtr = NULL;
    if (cxtNsPtr->commandPathLength!=0 && strncmp(name, "::", 2)
	    && !(flags & TCL_NAMESPACE_ONLY)) {
	size_t 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)) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
		}
	    }
	}

	/*
	 * Next, check along the path.
	 */

	for (i=0 ; i<cxtNsPtr->commandPathLength && cmdPtr==NULL ; 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)) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    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)) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
		}
	    }
	}
    } else {







|







|











|








|

















|







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
    /*
     * Find the namespace(s) that contain the command.
     */

    cmdPtr = NULL;
    if (cxtNsPtr->commandPathLength!=0 && strncmp(name, "::", 2)
	    && !(flags & TCL_NAMESPACE_ONLY)) {
	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_DEAD)) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
		}
	    }
	}

	/*
	 * Next, check along the path.
	 */

	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_DEAD)) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    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_DEAD)) {
		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
		if (entryPtr != NULL) {
		    cmdPtr = (Command *)Tcl_GetHashValue(entryPtr);
		}
	    }
	}
    } else {
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
    if (cmdPtr != NULL) {
	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);
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *







|
|







2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
    if (cmdPtr != NULL) {
	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, (char *)NULL);
    }
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
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
	     */

	    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);
	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);
    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);
    }
    if (SetNsNameFromAny(interp, objPtr) == TCL_OK) {
	NsNameGetIntRep(objPtr, resNamePtr);
	assert(resNamePtr != NULL);
	*nsPtrPtr = (Tcl_Namespace *) resNamePtr->nsPtr;
	return TCL_OK;
    }
    return TCL_ERROR;
}








|














|












|
|


|


|







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
	     */

	    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, (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;

    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_StoreInternalRep(objPtr, &nsNameType, NULL);
    }
    if (SetNsNameFromAny(interp, objPtr) == TCL_OK) {
	NsNameGetInternalRep(objPtr, resNamePtr);
	assert(resNamePtr != NULL);
	*nsPtrPtr = (Tcl_Namespace *) resNamePtr->nsPtr;
	return TCL_OK;
    }
    return TCL_ERROR;
}

2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceChildrenCmd(
    TCL_UNUSED(ClientData),
    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);







|







3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceChildrenCmd(
    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);
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
     * 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) == ':')) {
	    pattern = name;
	} else {
	    Tcl_DStringAppend(&buffer, nsPtr->fullName, -1);
	    if (nsPtr != globalNsPtr) {
		TclDStringAppendLiteral(&buffer, "::");
	    }
	    Tcl_DStringAppend(&buffer, name, -1);







|







3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
     * 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[0] == ':') && (name[1] == ':')) {
	    pattern = name;
	} else {
	    Tcl_DStringAppend(&buffer, nsPtr->fullName, -1);
	    if (nsPtr != globalNsPtr) {
		TclDStringAppendLiteral(&buffer, "::");
	    }
	    Tcl_DStringAppend(&buffer, name, -1);
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
 *	result in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceCodeCmd(
    TCL_UNUSED(ClientData),
    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;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "arg");
	return TCL_ERROR;
    }

    /*







|







|







3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
 *	result in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceCodeCmd(
    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;
    Tcl_Size length;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "arg");
	return TCL_ERROR;
    }

    /*
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceCurrentCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Namespace *currNsPtr;

    if (objc != 1) {







|







3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceCurrentCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Namespace *currNsPtr;

    if (objc != 1) {
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
 *	function returns an error message in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceDeleteCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *namespacePtr;
    const char *name;
    int i;







|







3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
 *	function returns an error message in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceDeleteCmd(
    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
     * 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)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "unknown namespace \"%s\" in namespace delete command",
		    TclGetString(objv[i])));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE",
		    TclGetString(objv[i]), NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * Okay, now delete each namespace.
     */







|

|


|







3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
     * 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_TEARDOWN)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "unknown namespace \"%s\" in namespace delete command",
		    TclGetString(objv[i])));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "NAMESPACE",
		    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
 *	result.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceEvalCmd(
    ClientData 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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    CmdFrame *invoker;
    int word;







|










|







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
 *	result.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceEvalCmd(
    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(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
    TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "eval",
	    NULL, NULL);
    return TclNREvalObjEx(interp, objPtr, 0, invoker, word);
}

static int
NsEval_Callback(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Namespace *namespacePtr = (Tcl_Namespace *)data[0];

    if (result == TCL_ERROR) {
	size_t length = strlen(namespacePtr->fullName);







|







3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
    TclNRAddCallback(interp, NsEval_Callback, namespacePtr, "eval",
	    NULL, NULL);
    return TclNREvalObjEx(interp, objPtr, 0, invoker, word);
}

static int
NsEval_Callback(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Namespace *namespacePtr = (Tcl_Namespace *)data[0];

    if (result == TCL_ERROR) {
	size_t length = strlen(namespacePtr->fullName);
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceExistsCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *namespacePtr;

    if (objc != 2) {







|







3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceExistsCmd(
    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
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceExportCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int firstArg, i;

    if (objc < 1) {







|







3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceExportCmd(
    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) {
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
 *	interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceForgetCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *pattern;
    int i, result;








|







3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
 *	interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceForgetCmd(
    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
 *	result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceImportCmd(
    TCL_UNUSED(ClientData),
    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;







|







3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
 *	result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceImportCmd(
    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;
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
 *	Returns a result in the Tcl interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceInscopeCmd(
    ClientData 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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *namespacePtr;
    CallFrame *framePtr, **framePtrPtr;
    int i;







|










|







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
 *	Returns a result in the Tcl interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceInscopeCmd(
    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(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;
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
 *	interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceOriginCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Command cmd, origCmd;
    Tcl_Obj *resultPtr;








|







3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
 *	interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceOriginCmd(
    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;

3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
    }
    TclNewObj(resultPtr);
    Tcl_GetCommandFullName(interp, origCmd, resultPtr);
    if (TclCheckEmptyString(resultPtr) == TCL_EMPTYSTRING_YES ) {
	Tcl_DecrRefCount(resultPtr);
	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;
}









|

|







3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
    }
    TclNewObj(resultPtr);
    Tcl_GetCommandFullName(interp, origCmd, resultPtr);
    if (TclCheckEmptyString(resultPtr) == TCL_EMPTYSTRING_YES ) {
	Tcl_DecrRefCount(resultPtr);
	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;
    }
    Tcl_SetObjResult(interp, resultPtr);
    return TCL_OK;
}


3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceParentCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *nsPtr;

    if (objc == 1) {







|







3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceParentCmd(
    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) {
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
 *	names that depend on the namespace for resolution).
 *
 *----------------------------------------------------------------------
 */

static int
NamespacePathCmd(
    TCL_UNUSED(ClientData),
    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_Obj **nsObjv;
    Tcl_Namespace **namespaceList = NULL;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?pathList?");
	return TCL_ERROR;
    }







|





|
|







4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
 *	names that depend on the namespace for resolution).
 *
 *----------------------------------------------------------------------
 */

static int
NamespacePathCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Namespace *nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
    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;
    }
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
    if (TclListObjGetElements(interp, objv[1], &nsObjc, &nsObjv) != TCL_OK) {
	goto badNamespace;
    }
    if (nsObjc != 0) {
	namespaceList = (Tcl_Namespace **)TclStackAlloc(interp,
		sizeof(Tcl_Namespace *) * nsObjc);

	for (i=0 ; i<(size_t)nsObjc ; i++) {
	    if (TclGetNamespaceFromObj(interp, nsObjv[i],
		    &namespaceList[i]) != TCL_OK) {
		goto badNamespace;
	    }
	}
    }








|







4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
    if (TclListObjGetElements(interp, objv[1], &nsObjc, &nsObjv) != TCL_OK) {
	goto badNamespace;
    }
    if (nsObjc != 0) {
	namespaceList = (Tcl_Namespace **)TclStackAlloc(interp,
		sizeof(Tcl_Namespace *) * nsObjc);

	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
 *
 *----------------------------------------------------------------------
 */

void
TclSetNsPath(
    Namespace *nsPtr,		/* Namespace whose path is to be set. */
    size_t 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;

	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;







|





|







4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
 *
 *----------------------------------------------------------------------
 */

void
TclSetNsPath(
    Namespace *nsPtr,		/* Namespace whose path is to be set. */
    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);
	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
 *----------------------------------------------------------------------
 */

static void
UnlinkNsPath(
    Namespace *nsPtr)
{
    size_t 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) {







|







4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
 *----------------------------------------------------------------------
 */

static void
UnlinkNsPath(
    Namespace *nsPtr)
{
    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
 *
 * 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
 *	the next time they are used.
 *
 *----------------------------------------------------------------------
 */

void
TclInvalidateNsPath(







|







4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
 *
 * 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 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
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceQualifiersCmd(
    TCL_UNUSED(ClientData),
    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++) {
	/* empty body */
    }
    while (--p >= name) {
	if ((*p == ':') && (p > name) && (*(p-1) == ':')) {
	    p -= 2;			/* Back up over the :: */
	    while ((p >= name) && (*p == ':')) {
		p--;			/* Back up over the preceeding : */
	    }
	    break;
	}
    }

    if (p >= name) {
	length = p-name+1;







|


















|



|

|
|







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
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceQualifiersCmd(
    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] != '\0';  p++) {
	/* empty body */
    }
    while (--p >= name) {
	if ((p[0] == ':') && (p > name) && (p[-1] == ':')) {
	    p -= 2;			/* Back up over the :: */
	    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
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceUnknownCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Namespace *currNsPtr;
    Tcl_Obj *resultPtr;
    int rc;







|







4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceUnknownCmd(
    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
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;
    Namespace *currNsPtr = (Namespace *) nsPtr;

    /*
     * Ensure that we check for errors *first* before we change anything.
     */

    if (handlerPtr != NULL) {







|







4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
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. */
{
    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
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceTailCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *name, *p;

    if (objc != 2) {







|







4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceTailCmd(
    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
     */

    name = TclGetString(objv[1]);
    for (p = name;  *p != '\0';  p++) {
	/* empty body */
    }
    while (--p > name) {
	if ((*p == ':') && (*(p-1) == ':')) {
	    p++;			/* Just after the last "::" */
	    break;
	}
    }

    if (p >= name) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(p, -1));







|







4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
     */

    name = TclGetString(objv[1]);
    for (p = name;  *p != '\0';  p++) {
	/* empty body */
    }
    while (--p > name) {
	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
 *	    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
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceUpvarCmd(
    TCL_UNUSED(ClientData),
    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;







|







|







4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
 *	    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 namespace. If anything goes
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceUpvarCmd(
    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
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceWhichCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    static const char *const opts[] = {
	"-command", "-variable", NULL
    };







|







4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
 *	wrong, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

static int
NamespaceWhichCmd(
    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
    };
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
static void
FreeNsNameInternalRep(
    Tcl_Obj *objPtr)	/* nsName object with internal representation
				 * to free. */
{
    ResolvedNsName *resNamePtr;

    NsNameGetIntRep(objPtr, resNamePtr);
    assert(resNamePtr != NULL);

    /*
     * Decrement the reference count of the namespace. If there are no more
     * references, free it up.
     */








|







4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
static void
FreeNsNameInternalRep(
    Tcl_Obj *objPtr)	/* nsName object with internal representation
				 * to free. */
{
    ResolvedNsName *resNamePtr;

    NsNameGetInternalRep(objPtr, resNamePtr);
    assert(resNamePtr != NULL);

    /*
     * Decrement the reference count of the namespace. If there are no more
     * references, free it up.
     */

4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
static void
DupNsNameInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
{
    ResolvedNsName *resNamePtr;

    NsNameGetIntRep(srcPtr, resNamePtr);
    assert(resNamePtr != NULL);
    NsNameSetIntRep(copyPtr, resNamePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * SetNsNameFromAny --
 *







|

|







4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
static void
DupNsNameInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
{
    ResolvedNsName *resNamePtr;

    NsNameGetInternalRep(srcPtr, resNamePtr);
    assert(resNamePtr != NULL);
    NsNameSetInternalRep(copyPtr, resNamePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * SetNsNameFromAny --
 *
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822

    nsPtr->refCount++;
    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);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetNamespaceCommandTable --







|


|







4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861

    nsPtr->refCount++;
    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;
    NsNameSetInternalRep(objPtr, resNamePtr);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetNamespaceCommandTable --
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
}

/*
 *----------------------------------------------------------------------
 *
 * TclLogCommandInfo --
 *
 *	This function is invoked after an error occurs in an interpreter. It
 *	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
 *	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). */
    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.
	 */

	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) {
	    length = strlen(command);
	}
	overflow = (length > (size_t)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_FindHashEntry(&iPtr->varTraces, (char *) varPtr);
	    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







|
|


|



















|
|











|
|

















|


|
















|







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
}

/*
 *----------------------------------------------------------------------
 *
 * TclLogCommandInfo --
 *
 *	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, 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. */
    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.
	 * 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 < 0) {
	    length = strlen(command);
	}
	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_FindHashEntry(&iPtr->varTraces, varPtr);
	    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
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001

	newObj = Tcl_DuplicateObj(iPtr->errorStack);
	Tcl_DecrRefCount(iPtr->errorStack);
	Tcl_IncrRefCount(newObj);
	iPtr->errorStack = newObj;
    }
    if (iPtr->resetErrorStack) {
	int len;

	iPtr->resetErrorStack = 0;
	Tcl_ListObjLength(interp, iPtr->errorStack, &len);

	/*
	 * Reset while keeping the list intrep as much as possible.
	 */

	Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, 0, NULL);
	if (pc != NULL) {
	    Tcl_Obj *innerContext;

	    innerContext = TclGetInnerContext(interp, pc, tosPtr);







|


|


|







5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040

	newObj = Tcl_DuplicateObj(iPtr->errorStack);
	Tcl_DecrRefCount(iPtr->errorStack);
	Tcl_IncrRefCount(newObj);
	iPtr->errorStack = newObj;
    }
    if (iPtr->resetErrorStack) {
	Tcl_Size len;

	iPtr->resetErrorStack = 0;
	TclListObjLength(interp, iPtr->errorStack, &len);

	/*
	 * 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
    } 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));
    } 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(







|







5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
    } 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(
		(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
 *----------------------------------------------------------------------
 */

void
TclErrorStackResetIf(
    Tcl_Interp *interp,
    const char *msg,
    size_t 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;

	iPtr->resetErrorStack = 0;
	Tcl_ListObjLength(interp, iPtr->errorStack, &len);

	/*
	 * Reset while keeping the list intrep 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));
    }







|












|


|


|







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
 *----------------------------------------------------------------------
 */

void
TclErrorStackResetIf(
    Tcl_Interp *interp,
    const char *msg,
    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) {
	Tcl_Size len;

	iPtr->resetErrorStack = 0;
	TclListObjLength(interp, iPtr->errorStack, &len);

	/*
	 * 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
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
				 * all bytes up to first null byte). */
{
    TclLogCommandInfo(interp, script, command, length, NULL, NULL);
}


/*







|







5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
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. */
    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);
}


/*

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
/*
 * 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.

 *
 * 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 functions (for overriding via Tcl_SetNotifier).
 */

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;
    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









|
|
|
>








|



|











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 © 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"

/*
 * Notifier hooks that are checked in the public wrappers for the default
 * notifier functions (for overriding via Tcl_SetNotifier).
 */

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;
    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
				 * 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
				 * 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;







|







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. */
    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
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);

/*
 *----------------------------------------------------------------------
 *
 * TclInitNotifier --
 *
 *	Initialize the thread local data structures for the notifier







|
|







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 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
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 */
    }

    Tcl_MutexLock(&(tsdPtr->queueMutex));
    for (evPtr = tsdPtr->firstEventPtr; evPtr != NULL; ) {
	hold = evPtr;
	evPtr = evPtr->nextPtr;
	Tcl_Free(hold);







|







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 */
    }

    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
 *	notifier functions.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetNotifier(
    Tcl_NotifierProcs *notifierProcPtr)
{
    tclNotifierHooks = *notifierProcPtr;
































}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateEventSource --
 *







|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
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(
    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
 *
 *	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));
 *	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
				 * checkProc. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    EventSource *sourcePtr = (EventSource *)Tcl_Alloc(sizeof(EventSource));

    sourcePtr->setupProc = setupProc;
    sourcePtr->checkProc = checkProc;







|
















|







284
285
286
287
288
289
290
291
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)(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. */
    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
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
				 * checkProc. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    EventSource *sourcePtr, *prevPtr;

    for (sourcePtr = tsdPtr->firstEventSourcePtr, prevPtr = NULL;
	    sourcePtr != NULL;







|







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. */
    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
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. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    QueueEvent(tsdPtr, evPtr, position);
}

/*







|
|







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. */
    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
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. */
{
    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);


    } 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:

 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
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. */
{
    Tcl_MutexLock(&(tsdPtr->queueMutex));



    if (position == 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) {
	/*
	 * 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) {
	/*
	 * 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));

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteEvents --
 *







|
|


















|
>
>



















>
|







|








|
|


>
>
>
|











|









|


















>







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. */
    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) {
	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
 *	operation is returned.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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. */
    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 & 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 & 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 & 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
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DeleteEvents(
    Tcl_EventDeleteProc *proc,	/* The function to call. */
    ClientData 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);







|







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. */
    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
 *	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
				 * 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)







|







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
				 * 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
	    }
	}
	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).
	 *
	 * 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) {







|
|
|
|
|
|







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 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
    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
     * avoid recursive calls.
     */

    tsdPtr->serviceMode = TCL_SERVICE_NONE;

    /*
     * Check async handlers first.







|







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 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
	    Tcl_AlertNotifier(tsdPtr->clientData);
	    break;
	}
    }
    Tcl_MutexUnlock(&listLock);
}































































































































































































































































/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
/*
 * 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
 *
 * 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"





|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * tclOO.c --
 *
 *	This file contains the object-system core (NB: not Tcl_Obj, but ::oo)
 *
 * 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"
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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 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 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	SquelchCachedName(Object *oPtr);

static int		PublicNRObjectCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static int		PrivateNRObjectCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static int		MyClassNRObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static void		MyClassDeleted(ClientData 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.







|
|
|








|
|

|
|


|


|


|


|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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(void *clientData);
static void		DeletedObjdefNamespace(void *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(void *clientData);
static void		ObjectNamespaceDeleted(void *clientData);
static Tcl_CommandTraceProc	ObjectRenamedTrace;
static inline void	RemoveClass(Class **list, size_t num, size_t idx);
static inline void	RemoveObject(Object **list, size_t num, size_t idx);
static inline void	SquelchCachedName(Object *oPtr);

static int		PublicNRObjectCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static int		PrivateNRObjectCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static int		MyClassNRObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static void		MyClassDeleted(void *clientData);

/*
 * Methods in the oo::object and oo::class classes. First, we define a helper
 * macro that makes building the method type declaration structure a lot
 * easier. No point in making life harder than it has to be!
 *
 * Note that the core methods don't need clone or free proc callbacks.
133
134
135
136
137
138
139
140

141


142
143
144
145
146
147
148
};

/*
 * Scripted parts of TclOO. First, the main script (cannot be outside this
 * file).
 */

static const char *initScript =

"package ifneeded TclOO " 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.







|
>

>
>







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
};

/*
 * Scripted parts of TclOO. First, the main script (cannot be outside this
 * file).
 */

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
 *
 * ----------------------------------------------------------------------
 */

static inline void
RemoveClass(
    Class **list,
    int num,
    int idx)
{
    for (; idx < num - 1; idx++) {
	list[idx] = list[idx + 1];
    }
    list[idx] = NULL;
}

static inline void
RemoveObject(
    Object **list,
    int num,
    int idx)
{
    for (; idx < num - 1; idx++) {
	list[idx] = list[idx + 1];
    }
    list[idx] = NULL;
}

/*
 * ----------------------------------------------------------------------







|
|

|








|
|

|







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
 *
 * ----------------------------------------------------------------------
 */

static inline void
RemoveClass(
    Class **list,
    size_t num,
    size_t idx)
{
    for (; idx + 1 < num; idx++) {
	list[idx] = list[idx + 1];
    }
    list[idx] = NULL;
}

static inline void
RemoveObject(
    Object **list,
    size_t num,
    size_t 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
    }

    /*
     * Run our initialization script and, if that works, declare the package
     * to be fully provided.
     */

    if (Tcl_EvalEx(interp, initScript, -1, 0) != TCL_OK) {
	return TCL_ERROR;
    }


    return Tcl_PkgProvideEx(interp, "TclOO", TCLOO_PATCHLEVEL,
	    (void *) &tclOOStubs);



}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetFoundation --
 *







|



>
|
|
>
>
>







252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
    }

    /*
     * Run our initialization script and, if that works, declare the package
     * to be fully provided.
     */

    if (Tcl_EvalEx(interp, initScript, TCL_INDEX_NONE, 0) != TCL_OK) {
	return TCL_ERROR;
    }

#ifndef TCL_NO_DEPRECATED
    Tcl_PkgProvideEx(interp, "TclOO", TCLOO_PATCHLEVEL,
	    &tclOOStubs);
#endif
    return Tcl_PkgProvideEx(interp, "tcl::oo", TCLOO_PATCHLEVEL,
	    &tclOOStubs);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetFoundation --
 *
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 Tcl_ThreadDataKey tsdKey;
    ThreadLocalData *tsdPtr =
	    (ThreadLocalData *)Tcl_GetThreadData(&tsdKey, sizeof(ThreadLocalData));
    Foundation *fPtr = (Foundation *)Tcl_Alloc(sizeof(Foundation));
    Tcl_Obj *namePtr;
    Tcl_DString buffer;
    Command *cmdPtr;
    int 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,
	    DeletedDefineNamespace);
    fPtr->objdefNs = Tcl_CreateNamespace(interp, "::oo::objdefine", fPtr,
	    DeletedObjdefNamespace);
    fPtr->helpersNs = Tcl_CreateNamespace(interp, "::oo::Helpers", fPtr,
	    DeletedHelpersNamespace);

    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");







|


















>







304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
    static Tcl_ThreadDataKey tsdKey;
    ThreadLocalData *tsdPtr =
	    (ThreadLocalData *)Tcl_GetThreadData(&tsdKey, sizeof(ThreadLocalData));
    Foundation *fPtr = (Foundation *)Tcl_Alloc(sizeof(Foundation));
    Tcl_Obj *namePtr;
    Tcl_DString buffer;
    Command *cmdPtr;
    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,
	    DeletedDefineNamespace);
    fPtr->objdefNs = Tcl_CreateNamespace(interp, "::oo::objdefine", fPtr,
	    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");
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
    /*
     * 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,
	    namePtr /* keeps ref */, 0 /* private */, NULL, NULL);
    fPtr->classCls->constructorPtr = (Method *) Tcl_NewMethod(interp,
	    (Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL);

    /*
     * Create non-object commands and plug ourselves into the Tcl [info]
     * ensemble.
     */








|

|







388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
    /*
     * 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");
    TclNewInstanceMethod(interp, (Tcl_Object) fPtr->classCls->thisPtr,
	    namePtr /* keeps ref */, 0 /* private */, NULL, NULL);
    fPtr->classCls->constructorPtr = (Method *) TclNewMethod(interp,
	    (Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL);

    /*
     * Create non-object commands and plug ourselves into the Tcl [info]
     * ensemble.
     */

418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
	return TCL_ERROR;
    }

    /*
     * Evaluate the remaining definitions, which are a compiled-in Tcl script.
     */

    return Tcl_EvalEx(interp, tclOOSetupScript, -1, 0);
}

/*
 * ----------------------------------------------------------------------
 *
 * InitClassSystemRoots --
 *







|







426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
	return TCL_ERROR;
    }

    /*
     * Evaluate the remaining definitions, which are a compiled-in Tcl script.
     */

    return Tcl_EvalEx(interp, tclOOSetupScript, TCL_INDEX_NONE, 0);
}

/*
 * ----------------------------------------------------------------------
 *
 * InitClassSystemRoots --
 *
445
446
447
448
449
450
451

452
453
454
455
456
457
458
    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;


    fPtr->objectCls = TclOOAllocClass(interp,
	    AllocObject(interp, "object", (Namespace *)fPtr->ooNs, NULL));
    /* Corresponding TclOODecrRefCount in KillFoudation */
    AddRef(fPtr->objectCls->thisPtr);

    /*







>







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
    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 */
    AddRef(fPtr->objectCls->thisPtr);

    /*
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
 *	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)
{
    Foundation *fPtr = (Foundation *)clientData;

    fPtr->helpersNs = NULL;
}

/*







|








|








|







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
 *	longer hold useful information.
 *
 * ----------------------------------------------------------------------
 */

static void
DeletedDefineNamespace(
    void *clientData)
{
    Foundation *fPtr = (Foundation *)clientData;

    fPtr->defineNs = NULL;
}

static void
DeletedObjdefNamespace(
    void *clientData)
{
    Foundation *fPtr = (Foundation *)clientData;

    fPtr->objdefNs = NULL;
}

static void
DeletedHelpersNamespace(
    void *clientData)
{
    Foundation *fPtr = (Foundation *)clientData;

    fPtr->helpersNs = NULL;
}

/*
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
	}
	Tcl_ResetResult(interp);
    }

    while (1) {
	char objName[10 + TCL_INTEGER_SPACE];

	sprintf(objName, "::oo::Obj%" TCL_Z_MODIFIER "u", ++fPtr->tsdPtr->nsCount);
	oPtr->namespacePtr = Tcl_CreateNamespace(interp, objName, oPtr, NULL);
	if (oPtr->namespacePtr != NULL) {
	    creationEpoch = fPtr->tsdPtr->nsCount;
	    break;
	}

	/*







|







652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
	}
	Tcl_ResetResult(interp);
    }

    while (1) {
	char objName[10 + TCL_INTEGER_SPACE];

	snprintf(objName, sizeof(objName), "::oo::Obj%" TCL_Z_MODIFIER "u", ++fPtr->tsdPtr->nsCount);
	oPtr->namespacePtr = Tcl_CreateNamespace(interp, objName, oPtr, NULL);
	if (oPtr->namespacePtr != NULL) {
	    creationEpoch = fPtr->tsdPtr->nsCount;
	    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
 *	of those commands when the object itself is deleted.
 *
 * ----------------------------------------------------------------------
 */

static void
MyDeleted(
    ClientData clientData)	/* Reference to the object whose [my] has been
				 * squelched. */
{
    Object *oPtr = (Object *)clientData;

    oPtr->myCommand = NULL;
}

static void
MyClassDeleted(
    ClientData 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. */
    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;








|









|




















|







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
 *	of those commands when the object itself is deleted.
 *
 * ----------------------------------------------------------------------
 */

static void
MyDeleted(
    void *clientData)	/* Reference to the object whose [my] has been
				 * squelched. */
{
    Object *oPtr = (Object *)clientData;

    oPtr->myCommand = NULL;
}

static void
MyClassDeleted(
    void *clientData)
{
    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(
    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;

949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967

void
TclOOReleaseClassContents(
    Tcl_Interp *interp,		/* The interpreter containing the class. */
    Object *oPtr)		/* The object representing the class. */
{
    FOREACH_HASH_DECLS;
    int i;
    Class *clsPtr = oPtr->classPtr, *tmpClsPtr;
    Method *mPtr;
    Foundation *fPtr = oPtr->fPtr;
    Tcl_Obj *variableObj;
    PrivateVariableMapping *privateVariable;

    /*
     * Sanity check!
     */

    if (!Destructing(oPtr)) {







|



|







958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976

void
TclOOReleaseClassContents(
    Tcl_Interp *interp,		/* The interpreter containing the class. */
    Object *oPtr)		/* The object representing the class. */
{
    FOREACH_HASH_DECLS;
    Tcl_Size i;
    Class *clsPtr = oPtr->classPtr, *tmpClsPtr;
    Method *mPtr;
    Foundation *fPtr = oPtr->fPtr;
    Tcl_Obj *variableObj, *propertyObj;
    PrivateVariableMapping *privateVariable;

    /*
     * Sanity check!
     */

    if (!Destructing(oPtr)) {
1005
1006
1007
1008
1009
1010
1011























1012
1013
1014
1015
1016
1017
1018
	FOREACH_HASH_VALUE(callPtr, clsPtr->classChainCache) {
	    TclOODeleteChain(callPtr);
	}
	Tcl_DeleteHashTable(clsPtr->classChainCache);
	Tcl_Free(clsPtr->classChainCache);
	clsPtr->classChainCache = NULL;
    }
























    /*
     * Squelch our filter list.
     */

    if (clsPtr->filters.num) {
	Tcl_Obj *filterObj;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	FOREACH_HASH_VALUE(callPtr, clsPtr->classChainCache) {
	    TclOODeleteChain(callPtr);
	}
	Tcl_DeleteHashTable(clsPtr->classChainCache);
	Tcl_Free(clsPtr->classChainCache);
	clsPtr->classChainCache = NULL;
    }

    /*
     * Squelch the property lists.
     */

    if (clsPtr->properties.allReadableCache) {
	Tcl_DecrRefCount(clsPtr->properties.allReadableCache);
    }
    if (clsPtr->properties.allWritableCache) {
	Tcl_DecrRefCount(clsPtr->properties.allWritableCache);
    }
    if (clsPtr->properties.readable.num) {
	FOREACH(propertyObj, clsPtr->properties.readable) {
	    Tcl_DecrRefCount(propertyObj);
	}
	Tcl_Free(clsPtr->properties.readable.list);
    }
    if (clsPtr->properties.writable.num) {
	FOREACH(propertyObj, clsPtr->properties.writable) {
	    Tcl_DecrRefCount(propertyObj);
	}
	Tcl_Free(clsPtr->properties.writable.list);
    }

    /*
     * 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

    /*
     * Squelch our metadata.
     */

    if (clsPtr->metadataPtr != NULL) {
	Tcl_ObjectMetadataType *metadataTypePtr;
	ClientData value;

	FOREACH_HASH(metadataTypePtr, value, clsPtr->metadataPtr) {
	    metadataTypePtr->deleteProc(value);
	}
	Tcl_DeleteHashTable(clsPtr->metadataPtr);
	Tcl_Free(clsPtr->metadataPtr);
	clsPtr->metadataPtr = NULL;







|







1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073

    /*
     * Squelch our metadata.
     */

    if (clsPtr->metadataPtr != NULL) {
	Tcl_ObjectMetadataType *metadataTypePtr;
	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
 *	(interpreter teardown is complex!)
 *
 * ----------------------------------------------------------------------
 */

static void
ObjectNamespaceDeleted(
    ClientData clientData)	/* Pointer to the class whose namespace is
				 * being deleted. */
{
    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;

    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
     * records.  This is the flag that
     */

    oPtr->flags |= OBJECT_DESTRUCTING;

    /*
     * Let the dominoes fall!







|







|


|












|







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
 *	(interpreter teardown is complex!)
 *
 * ----------------------------------------------------------------------
 */

static void
ObjectNamespaceDeleted(
    void *clientData)	/* Pointer to the class whose namespace is
				 * being deleted. */
{
    Object *oPtr = (Object *)clientData;
    Foundation *fPtr = oPtr->fPtr;
    FOREACH_HASH_DECLS;
    Class *mixinPtr;
    Method *mPtr;
    Tcl_Obj *filterObj, *variableObj, *propertyObj;
    PrivateVariableMapping *privateVariable;
    Tcl_Interp *interp = oPtr->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 bookkeeping
     * records.  This is the flag that
     */

    oPtr->flags |= OBJECT_DESTRUCTING;

    /*
     * Let the dominoes fall!
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
     * 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,
	 */
    } else {
	/*
	 * The namespace must have been deleted directly.  Delete the command
	 * as well.
	 */








|







1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
     * still exists) because otherwise its pointer to the object points into
     * freed memory.
     */

    if (((Command *) oPtr->command)->flags && CMD_DYING) {
	/*
	 * Something has already started the command deletion process. We can
	 * go ahead and clean up the namespace,
	 */
    } else {
	/*
	 * The namespace must have been deleted directly.  Delete the command
	 * as well.
	 */

1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265























1266
1267
1268
1269
1270
1271
1272
	TclOODeleteChainCache(oPtr->chainCache);
    }

    SquelchCachedName(oPtr);

    if (oPtr->metadataPtr != NULL) {
	Tcl_ObjectMetadataType *metadataTypePtr;
	ClientData value;

	FOREACH_HASH(metadataTypePtr, value, oPtr->metadataPtr) {
	    metadataTypePtr->deleteProc(value);
	}
	Tcl_DeleteHashTable(oPtr->metadataPtr);
	Tcl_Free(oPtr->metadataPtr);
	oPtr->metadataPtr = NULL;
    }
























    /*
     * 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







|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	TclOODeleteChainCache(oPtr->chainCache);
    }

    SquelchCachedName(oPtr);

    if (oPtr->metadataPtr != NULL) {
	Tcl_ObjectMetadataType *metadataTypePtr;
	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.
     */

    if (oPtr->properties.allReadableCache) {
	Tcl_DecrRefCount(oPtr->properties.allReadableCache);
    }
    if (oPtr->properties.allWritableCache) {
	Tcl_DecrRefCount(oPtr->properties.allWritableCache);
    }
    if (oPtr->properties.readable.num) {
	FOREACH(propertyObj, oPtr->properties.readable) {
	    Tcl_DecrRefCount(propertyObj);
	}
	Tcl_Free(oPtr->properties.readable.list);
    }
    if (oPtr->properties.writable.num) {
	FOREACH(propertyObj, oPtr->properties.writable) {
	    Tcl_DecrRefCount(propertyObj);
	}
	Tcl_Free(oPtr->properties.writable.list);
    }

    /*
     * 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
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
 * TclOOObjectDestroyed --
 *
 *	Returns TCL_OK if an object is entirely deleted, i.e. the destruction
 *	sequence has completed.
 *
 * ----------------------------------------------------------------------
 */

int 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. */
{

    int i, res = 0;
    Object *instPtr;

    FOREACH(instPtr, clsPtr->instances) {
	if (oPtr == instPtr) {
	    RemoveItem(Object, clsPtr->instances, i);
	    TclOODecrRefCount(oPtr);
	    res++;







>
|
>
>




















>
|







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
 * TclOOObjectDestroyed --
 *
 *	Returns TCL_OK if an object is entirely deleted, i.e. the destruction
 *	sequence has completed.
 *
 * ----------------------------------------------------------------------
 */
int
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 res = 0;
    Object *instPtr;

    FOREACH(instPtr, clsPtr->instances) {
	if (oPtr == instPtr) {
	    RemoveItem(Object, clsPtr->instances, i);
	    TclOODecrRefCount(oPtr);
	    res++;
1413
1414
1415
1416
1417
1418
1419

1420
1421
1422
1423
1424
1425
1426
1427

int
TclOORemoveFromMixins(
    Class *mixinPtr,		/* The mixin to remove. */
    Object *oPtr)		/* The object (possibly) containing the
				 * reference to the mixin. */
{

    int i, res = 0;
    Class *mixPtr;

    FOREACH(mixPtr, oPtr->mixins) {
	if (mixinPtr == mixPtr) {
	    RemoveItem(Class, oPtr->mixins, i);
	    TclOODecrRefCount(mixPtr->thisPtr);
	    res++;







>
|







1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487

int
TclOORemoveFromMixins(
    Class *mixinPtr,		/* The mixin to remove. */
    Object *oPtr)		/* The object (possibly) containing the
				 * reference to the mixin. */
{
    Tcl_Size i;
    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

int
TclOORemoveFromSubclasses(
    Class *subPtr,		/* The subclass to remove. */
    Class *superPtr)		/* The superclass to possibly remove the
				 * subclass reference from. */
{

    int i, res = 0;
    Class *subclsPtr;

    FOREACH(subclsPtr, superPtr->subclasses) {
	if (subPtr == subclsPtr) {
	    RemoveItem(Class, superPtr->subclasses, i);
	    TclOODecrRefCount(subPtr->thisPtr);
	    res++;







>
|







1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523

int
TclOORemoveFromSubclasses(
    Class *subPtr,		/* The subclass to remove. */
    Class *superPtr)		/* The superclass to possibly remove the
				 * subclass reference from. */
{
    Tcl_Size i;
    int res = 0;
    Class *subclsPtr;

    FOREACH(subclsPtr, superPtr->subclasses) {
	if (subPtr == subclsPtr) {
	    RemoveItem(Class, superPtr->subclasses, i);
	    TclOODecrRefCount(subPtr->thisPtr);
	    res++;
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
1526

int
TclOORemoveFromMixinSubs(
    Class *subPtr,		/* The subclass to remove. */
    Class *superPtr)		/* The superclass to possibly remove the
				 * subclass reference from. */
{

    int i, res = 0;
    Class *subclsPtr;

    FOREACH(subclsPtr, superPtr->mixinSubs) {
	if (subPtr == subclsPtr) {
	    RemoveItem(Class, superPtr->mixinSubs, i);
	    TclOODecrRefCount(subPtr->thisPtr);
	    res++;







>
|







1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588

int
TclOORemoveFromMixinSubs(
    Class *subPtr,		/* The subclass to remove. */
    Class *superPtr)		/* The superclass to possibly remove the
				 * subclass reference from. */
{
    Tcl_Size i;
    int res = 0;
    Class *subclsPtr;

    FOREACH(subclsPtr, superPtr->mixinSubs) {
	if (subPtr == subclsPtr) {
	    RemoveItem(Class, superPtr->mixinSubs, i);
	    TclOODecrRefCount(subPtr->thisPtr);
	    res++;
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
    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
				 * do not call constructor. */
    Tcl_Obj *const *objv,	/* Argument list. */
    int skip)			/* Number of arguments to _not_ pass to the
				 * constructor. */
{
    Class *classPtr = (Class *) cls;
    Object *oPtr;
    ClientData 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) {
	CallContext *contextPtr =
		TclOOGetCallContext(oPtr, NULL, CONSTRUCTOR, NULL, NULL, NULL);

	if (contextPtr != NULL) {
	    int isRoot, result;
	    Tcl_InterpState state;








|


|




|











|







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
    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. */
    Tcl_Size objc,			/* Number of arguments. Negative value means
				 * do not call constructor. */
    Tcl_Obj *const *objv,	/* Argument list. */
    Tcl_Size skip)			/* Number of arguments to _not_ pass to the
				 * constructor. */
{
    Class *classPtr = (Class *) cls;
    Object *oPtr;
    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 != 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
    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
				 * do not call constructor. */
    Tcl_Obj *const *objv,	/* Argument list. */
    int 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
     * object cloning only). If there aren't any constructors, we do nothing.
     */

    if (objc < 0) {
	*objectPtr = (Tcl_Object) oPtr;
	return TCL_OK;
    }







|


|















|







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
    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. */
    Tcl_Size objc,			/* Number of arguments. Negative value means
				 * do not call constructor. */
    Tcl_Obj *const *objv,	/* Argument list. */
    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 == 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
	 */

	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);
	    return NULL;
	}
    }

    /*
     * Create the object.
     */







|







1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
	 */

	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", (char *)NULL);
	    return NULL;
	}
    }

    /*
     * Create the object.
     */
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
	oPtr->classPtr = NULL;
    }
    return oPtr;
}

static int
FinalizeAlloc(
    ClientData 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];

    /*
     * 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);
	result = TCL_ERROR;
    }
    if (result != TCL_OK) {
	Tcl_DiscardInterpState(state);

	/*
	 * Take care to not delete a deleted object; that would be bad. [Bug







|
















|







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
	oPtr->classPtr = NULL;
    }
    return oPtr;
}

static int
FinalizeAlloc(
    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];

    /*
     * 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", (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
    Object *oPtr = (Object *) sourceObject, *o2Ptr;
    FOREACH_HASH_DECLS;
    Method *mPtr;
    Class *mixinPtr;
    CallContext *contextPtr;
    Tcl_Obj *keyPtr, *filterObj, *variableObj, *args[3];
    PrivateVariableMapping *privateVariable;

    int i, 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);
	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);
    if (o2Ptr == NULL) {
	return NULL;
    }

    /*
     * Copy the object-local methods to the new object.







>
|








|








|







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
    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 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", (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, TCL_INDEX_NONE,
	    NULL, -1);
    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

    /*
     * Copy the object's metadata.
     */

    if (oPtr->metadataPtr != NULL) {
	Tcl_ObjectMetadataType *metadataTypePtr;
	ClientData value, duplicate;

	FOREACH_HASH(metadataTypePtr, value, oPtr->metadataPtr) {
	    if (metadataTypePtr->cloneProc == NULL) {
		duplicate = value;
	    } else {
		if (metadataTypePtr->cloneProc(interp, value,
			&duplicate) != TCL_OK) {







|







2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098

    /*
     * Copy the object's metadata.
     */

    if (oPtr->metadataPtr != NULL) {
	Tcl_ObjectMetadataType *metadataTypePtr;
	void *value, *duplicate;

	FOREACH_HASH(metadataTypePtr, value, oPtr->metadataPtr) {
	    if (metadataTypePtr->cloneProc == NULL) {
		duplicate = value;
	    } else {
		if (metadataTypePtr->cloneProc(interp, value,
			&duplicate) != TCL_OK) {
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180

	/*
	 * Duplicate the class's metadata.
	 */

	if (clsPtr->metadataPtr != NULL) {
	    Tcl_ObjectMetadataType *metadataTypePtr;
	    ClientData value, duplicate;

	    FOREACH_HASH(metadataTypePtr, value, clsPtr->metadataPtr) {
		if (metadataTypePtr->cloneProc == NULL) {
		    duplicate = value;
		} else {
		    if (metadataTypePtr->cloneProc(interp, value,
			    &duplicate) != TCL_OK) {







|







2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243

	/*
	 * Duplicate the class's metadata.
	 */

	if (clsPtr->metadataPtr != NULL) {
	    Tcl_ObjectMetadataType *metadataTypePtr;
	    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
CloneObjectMethod(
    Tcl_Interp *interp,
    Object *oPtr,
    Method *mPtr,
    Tcl_Obj *namePtr)
{
    if (mPtr->typePtr == NULL) {
	Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
		mPtr->flags & PUBLIC_METHOD, NULL, NULL);
    } else if (mPtr->typePtr->cloneProc) {
	ClientData newClientData;

	if (mPtr->typePtr->cloneProc(interp, mPtr->clientData,
		&newClientData) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
		mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, newClientData);
    } else {
	Tcl_NewInstanceMethod(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,
		namePtr, mPtr->flags & PUBLIC_METHOD, NULL, NULL);
    } else if (mPtr->typePtr->cloneProc) {
	ClientData newClientData;

	if (mPtr->typePtr->cloneProc(interp, mPtr->clientData,
		&newClientData) != TCL_OK) {
	    return TCL_ERROR;
	}
	m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr,
		namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr,
		newClientData);
    } else {
	m2Ptr = (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr,
		namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr,
		mPtr->clientData);
    }
    if (m2PtrPtr != NULL) {
	*m2PtrPtr = m2Ptr;
    }
    return TCL_OK;







|


|





|


|
















|


|





|



|







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
CloneObjectMethod(
    Tcl_Interp *interp,
    Object *oPtr,
    Method *mPtr,
    Tcl_Obj *namePtr)
{
    if (mPtr->typePtr == NULL) {
	TclNewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
		mPtr->flags & PUBLIC_METHOD, NULL, NULL);
    } else if (mPtr->typePtr->cloneProc) {
	void *newClientData;

	if (mPtr->typePtr->cloneProc(interp, mPtr->clientData,
		&newClientData) != TCL_OK) {
	    return TCL_ERROR;
	}
	TclNewInstanceMethod(interp, (Tcl_Object) oPtr, namePtr,
		mPtr->flags & PUBLIC_METHOD, mPtr->typePtr, newClientData);
    } else {
	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 *) TclNewMethod(interp, (Tcl_Class) clsPtr,
		namePtr, mPtr->flags & PUBLIC_METHOD, NULL, NULL);
    } else if (mPtr->typePtr->cloneProc) {
	void *newClientData;

	if (mPtr->typePtr->cloneProc(interp, mPtr->clientData,
		&newClientData) != TCL_OK) {
	    return TCL_ERROR;
	}
	m2Ptr = (Method *) TclNewMethod(interp, (Tcl_Class) clsPtr,
		namePtr, mPtr->flags & PUBLIC_METHOD, mPtr->typePtr,
		newClientData);
    } else {
	m2Ptr = (Method *) TclNewMethod(interp, (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
 *	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
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);

    /*
     * 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)
{
    Class *clsPtr = (Class *) clazz;
    Tcl_HashEntry *hPtr;
    int isNew;

    /*
     * Attach the metadata store if not done already.







|




















|















|







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
 *	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.
 *
 * ----------------------------------------------------------------------
 */

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, 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,
    void *metadata)
{
    Class *clsPtr = (Class *) clazz;
    Tcl_HashEntry *hPtr;
    int isNew;

    /*
     * Attach the metadata store if not done already.
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
    }

    /*
     * If the metadata is NULL, we're deleting the metadata for the type.
     */

    if (metadata == NULL) {
	hPtr = Tcl_FindHashEntry(clsPtr->metadataPtr, (char *) 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);
    if (!isNew) {
	typePtr->deleteProc(Tcl_GetHashValue(hPtr));
    }
    Tcl_SetHashValue(hPtr, metadata);
}

ClientData
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);

    /*
     * 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)
{
    Object *oPtr = (Object *) object;
    Tcl_HashEntry *hPtr;
    int isNew;

    /*
     * Attach the metadata store if not done already.







|












|






|




















|















|







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
    }

    /*
     * If the metadata is NULL, we're deleting the metadata for the type.
     */

    if (metadata == NULL) {
	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, typePtr, &isNew);
    if (!isNew) {
	typePtr->deleteProc(Tcl_GetHashValue(hPtr));
    }
    Tcl_SetHashValue(hPtr, metadata);
}

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, 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,
    void *metadata)
{
    Object *oPtr = (Object *) object;
    Tcl_HashEntry *hPtr;
    int isNew;

    /*
     * Attach the metadata store if not done already.
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
    }

    /*
     * If the metadata is NULL, we're deleting the metadata for the type.
     */

    if (metadata == NULL) {
	hPtr = Tcl_FindHashEntry(oPtr->metadataPtr, (char *) 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);
    if (!isNew) {
	typePtr->deleteProc(Tcl_GetHashValue(hPtr));
    }
    Tcl_SetHashValue(hPtr, metadata);
}

/*







|












|







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
    }

    /*
     * If the metadata is NULL, we're deleting the metadata for the type.
     */

    if (metadata == NULL) {
	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, 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
 *	function. Note that the core is function is NRE-aware.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOPublicObjectCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return Tcl_NRCallObjProc(interp, PublicNRObjectCmd, clientData,objc,objv);
}

static int
PublicNRObjectCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return TclOOObjectCmdCore((Object *)clientData, interp, objc, objv, PUBLIC_METHOD,
	    NULL);
}

int
TclOOPrivateObjectCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return Tcl_NRCallObjProc(interp, PrivateNRObjectCmd,clientData,objc,objv);
}

static int
PrivateNRObjectCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    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_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,







|









|










|









|




















|







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
 *	function. Note that the core is function is NRE-aware.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOPublicObjectCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return Tcl_NRCallObjProc(interp, PublicNRObjectCmd, clientData,objc,objv);
}

static int
PublicNRObjectCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return TclOOObjectCmdCore((Object *)clientData, interp, objc, objv, PUBLIC_METHOD,
	    NULL);
}

int
TclOOPrivateObjectCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return Tcl_NRCallObjProc(interp, PrivateNRObjectCmd,clientData,objc,objv);
}

static int
PrivateNRObjectCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    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). */
    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
 *	Special trap door to allow an object to delegate simply to its class.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOMyClassObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return Tcl_NRCallObjProc(interp, MyClassNRObjCmd, clientData, objc, objv);
}

static int
MyClassNRObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *)clientData;

    if (objc < 2) {







|









|







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
 *	Special trap door to allow an object to delegate simply to its class.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOMyClassObjCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    return Tcl_NRCallObjProc(interp, MyClassNRObjCmd, clientData, objc, objv);
}

static int
MyClassNRObjCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *)clientData;

    if (objc < 2) {
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
 * ----------------------------------------------------------------------
 */

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_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). */







|







2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
 * ----------------------------------------------------------------------
 */

int
TclOOObjectCmdCore(
    Object *oPtr,		/* The object being invoked. */
    Tcl_Interp *interp,		/* The interpreter containing the object. */
    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). */
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
		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);
	    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);
	    return TCL_ERROR;
	}
    }

    /*
     * Check to see if we need to apply magical tricks to start part way
     * through the call chain.







|
















|







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
		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), (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), (char *)NULL);
	    return TCL_ERROR;
	}
    }

    /*
     * Check to see if we need to apply magical tricks to start part way
     * through the call chain.
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
		break;
	    }
	}
	if (contextPtr->index >= contextPtr->callPtr->numChain) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "no valid method implementation", -1));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		    TclGetString(methodNamePtr), 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[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    /*
     * Dispose of the call chain, which drops the lock on the object's
     * structure.
     */







|
















|







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
		break;
	    }
	}
	if (contextPtr->index >= contextPtr->callPtr->numChain) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "no valid method implementation", -1));
	    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
		    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(
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    /*
     * Dispose of the call chain, which drops the lock on the object's
     * structure.
     */
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
 * ----------------------------------------------------------------------
 */

int
Tcl_ObjectContextInvokeNext(
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv,
    int skip)
{
    CallContext *contextPtr = (CallContext *) context;
    int savedIndex = contextPtr->index;
    int 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)







|

|


|
|







2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
 * ----------------------------------------------------------------------
 */

int
Tcl_ObjectContextInvokeNext(
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    Tcl_Size objc,
    Tcl_Obj *const *objv,
    Tcl_Size skip)
{
    CallContext *contextPtr = (CallContext *) context;
    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
	    methodType = "destructor";
	} else {
	    methodType = "method";
	}

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"no next %s implementation", methodType));
	Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", 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







|







2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
	    methodType = "destructor";
	} else {
	    methodType = "method";
	}

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"no next %s implementation", methodType));
	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
    return result;
}

int
TclNRObjectContextInvokeNext(
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv,
    int 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







|

|







2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
    return result;
}

int
TclNRObjectContextInvokeNext(
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    Tcl_Size objc,
    Tcl_Obj *const *objv,
    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
	    methodType = "destructor";
	} else {
	    methodType = "method";
	}

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"no next %s implementation", methodType));
	Tcl_SetErrorCode(interp, "TCL", "OO", "NOTHING_NEXT", 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







|







2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
	    methodType = "destructor";
	} else {
	    methodType = "method";
	}

	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"no next %s implementation", methodType));
	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
     */

    return TclOOInvokeContext(contextPtr, interp, objc, objv);
}

static int
FinalizeNext(
    ClientData data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];

    /*
     * Restore the call chain context index as we've finished the inner invoke







|







2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
     */

    return TclOOInvokeContext(contextPtr, interp, objc, objv);
}

static int
FinalizeNext(
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];

    /*
     * Restore the call chain context index as we've finished the inner invoke
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
    }
    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);
    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;
    Class *superPtr;

  tailRecurse:
    if (startPtr == targetPtr) {
	return 1;
    }
    if (startPtr->superclasses.num == 1 && startPtr->mixins.num == 0) {







|



















|







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
    }
    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),
	    (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)
{
    Tcl_Size i;
    Class *superPtr;

  tailRecurse:
    if (startPtr == targetPtr) {
	return 1;
    }
    if (startPtr->superclasses.num == 1 && startPtr->mixins.num == 0) {
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
Tcl_Object
Tcl_ObjectContextObject(
    Tcl_ObjectContext context)
{
    return (Tcl_Object) ((CallContext *)context)->oPtr;
}

int
Tcl_ObjectContextSkippedArgs(
    Tcl_ObjectContext context)
{
    return ((CallContext *)context)->skip;
}

Tcl_Namespace *







|







3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
Tcl_Object
Tcl_ObjectContextObject(
    Tcl_ObjectContext context)
{
    return (Tcl_Object) ((CallContext *)context)->oPtr;
}

Tcl_Size
Tcl_ObjectContextSkippedArgs(
    Tcl_ObjectContext context)
{
    return ((CallContext *)context)->skip;
}

Tcl_Namespace *
3133
3134
3135
3136
3137
3138
3139




















3140
3141
3142
3143
3144
3145
3146
3147
void
Tcl_ObjectSetMethodNameMapper(
    Tcl_Object object,
    Tcl_ObjectMapMethodNameProc *mapMethodNameProc)
{
    ((Object *) object)->mapMethodNameProc = mapMethodNameProc;
}





















/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








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
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
# 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.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

library tclOO

######################################################################







|







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 © 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
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)
}
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)
}
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)
}
declare 24 {
    Tcl_ObjectMapMethodNameProc *Tcl_ObjectGetMethodNameMapper(
	    Tcl_Object object)
}
declare 25 {
    void Tcl_ObjectSetMethodNameMapper(Tcl_Object object,







|
|














|



















|
|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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, 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 {
    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, 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
}
declare 28 {
    Tcl_Obj *Tcl_GetObjectName(Tcl_Interp *interp, Tcl_Object object)
}
declare 29 {
    int Tcl_MethodIsPrivate(Tcl_Method method)
}





















######################################################################
# 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.
#








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







125
126
127
128
129
130
131
132
133
134
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
}
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,
	    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,







|







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, 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
	    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_Obj *const *objv)
}
declare 12 {
    void TclOOObjectSetFilters(Object *oPtr, int numFilters,
	    Tcl_Obj *const *filters)
}
declare 13 {
    void TclOOClassSetFilters(Tcl_Interp *interp, Class *classPtr,
	    int numFilters, Tcl_Obj *const *filters)
}
declare 14 {
    void TclOOObjectSetMixins(Object *oPtr, int numMixins,
	    Class *const *mixins)
}
declare 15 {
    void TclOOClassSetMixins(Tcl_Interp *interp, Class *classPtr,
	    int numMixins, Class *const *mixins)
}

return

# Local Variables:
# mode: tcl
# End:







|



|




|


|




|







210
211
212
213
214
215
216
217
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, Tcl_Size objc,
	    Tcl_Obj *const *objv)
}
declare 12 {
    void TclOOObjectSetFilters(Object *oPtr, Tcl_Size numFilters,
	    Tcl_Obj *const *filters)
}
declare 13 {
    void TclOOClassSetFilters(Tcl_Interp *interp, Class *classPtr,
	    Tcl_Size numFilters, Tcl_Obj *const *filters)
}
declare 14 {
    void TclOOObjectSetMixins(Object *oPtr, Tcl_Size numMixins,
	    Class *const *mixins)
}
declare 15 {
    void TclOOClassSetMixins(Tcl_Interp *interp, Class *classPtr,
	    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
 *
 * tests/oo.test
 * tests/ooNext2.test
 * unix/tclooConfig.sh
 * win/tclooConfig.sh
 */

#define TCLOO_VERSION "1.2.0"
#define TCLOO_PATCHLEVEL TCLOO_VERSION

#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)
#ifndef USE_TCL_STUBS
#   define TclOOInitializeStubs(interp, version) (TCLOO_PATCHLEVEL)
#endif

/*
 * These are opaque types.
 */







|
|














|







20
21
22
23
24
25
26
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.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_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
 * 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);






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 {
    int version;		/* Structure version field. Always to be equal
				 * to TCL_OO_METHOD_VERSION_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;






















/*
 * 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

/*
 * Visibility constants for the flags parameter to Tcl_NewMethod and
 * Tcl_NewInstanceMethod.
 */








>
>
>
>
>
>















|














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
 * 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 {
    int version;		/* Structure version field. Always to be equal
				 * 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 {
    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_1 1
#define TCL_OO_METHOD_VERSION_2 2
#define TCL_OO_METHOD_VERSION_CURRENT 1

/*
 * Visibility constants for the flags parameter to Tcl_NewMethod and
 * Tcl_NewInstanceMethod.
 */

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
/*
 * 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
 *
 * 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 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;






|










>







1
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 © 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
{
    TclNRAddCallback(interp, FinalizeConstruction, NULL, NULL, NULL, NULL);
    return (Tcl_Object *) &(TOP_CB(interp)->data[0]);
}

static int
FinalizeConstruction(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Object *oPtr = (Object *)data[0];

    if (result != TCL_OK) {
	return result;







|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
{
    TclNRAddCallback(interp, FinalizeConstruction, NULL, NULL, NULL, NULL);
    return (Tcl_Object *) &(TOP_CB(interp)->data[0]);
}

static int
FinalizeConstruction(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Object *oPtr = (Object *)data[0];

    if (result != TCL_OK) {
	return result;
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98
99
 *	Implementation for oo::class constructor.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_Constructor(
    TCL_UNUSED(ClientData),
    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,
		"?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).
     */







|








|
>
|


|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
 *	Implementation for oo::class constructor.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_Constructor(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    Tcl_Obj **invoke, *nameObj;

    size_t skip = Tcl_ObjectContextSkippedArgs(context);
    if ((size_t)objc > skip + 1) {
	Tcl_WrongNumArgs(interp, skip, objv,
		"?definitionScript?");
	return TCL_ERROR;
    } else if ((size_t)objc == skip) {
	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).
     */
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
     */

    return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL);
}

static int
DecrRefsPostClassConstructor(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj **invoke = (Tcl_Obj **)data[0];
    Object *oPtr = (Object *)data[1];
    Tcl_InterpState saved;
    int code;







|







132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
     */

    return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL);
}

static int
DecrRefsPostClassConstructor(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj **invoke = (Tcl_Obj **)data[0];
    Object *oPtr = (Object *)data[1];
    Tcl_InterpState saved;
    int code;
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
 *	Implementation for oo::class->create method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_Create(
    TCL_UNUSED(ClientData),
    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;

    /*
     * 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);
	return TCL_ERROR;
    }

    /*
     * Check we have the right number of (sensible) arguments.
     */

    if (objc - Tcl_ObjectContextSkippedArgs(context) < 1) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"objectName ?arg ...?");
	return TCL_ERROR;
    }
    objName = TclGetStringFromObj(
	    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);
	return TCL_ERROR;
    }

    /*
     * Make the object and return its name.
     */








|








|











|







|




|




|







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
 *	Implementation for oo::class->create method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_Create(
    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;
    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", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Check we have the right number of (sensible) arguments.
     */

    if (objc < 1 + Tcl_ObjectContextSkippedArgs(context)) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"objectName ?arg ...?");
	return TCL_ERROR;
    }
    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", (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
 *	Implementation for oo::class->createWithNamespace method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_CreateNs(
    TCL_UNUSED(ClientData),
    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;

    /*
     * 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);
	return TCL_ERROR;
    }

    /*
     * Check we have the right number of (sensible) arguments.
     */

    if (objc - Tcl_ObjectContextSkippedArgs(context) < 2) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"objectName namespaceName ?arg ...?");
	return TCL_ERROR;
    }
    objName = TclGetStringFromObj(
	    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);
	return TCL_ERROR;
    }
    nsName = TclGetStringFromObj(
	    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);
	return TCL_ERROR;
    }

    /*
     * Make the object and return its name.
     */








|








|











|







|




|




|


|




|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
 *	Implementation for oo::class->createWithNamespace method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_CreateNs(
    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;
    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", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Check we have the right number of (sensible) arguments.
     */

    if (objc + 1 < Tcl_ObjectContextSkippedArgs(context) + 3) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"objectName namespaceName ?arg ...?");
	return TCL_ERROR;
    }
    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", (char *)NULL);
	return TCL_ERROR;
    }
    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", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Make the object and return its name.
     */

308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
 *	Implementation for oo::class->new method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_New(
    TCL_UNUSED(ClientData),
    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);
	return TCL_ERROR;
    }

    /*
     * Make the object and return its name.
     */








|


















|







310
311
312
313
314
315
316
317
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
 *	Implementation for oo::class->new method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_New(
    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", (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
 *	Implementation for oo::object->destroy method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_Destroy(
    TCL_UNUSED(ClientData),
    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)) {
	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,







|









|







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
 *	Implementation for oo::object->destroy method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_Destroy(
    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 != (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
	Tcl_DeleteCommandFromToken(interp, oPtr->command);
    }
    return TCL_OK;
}

static int
AfterNRDestructor(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];

    if (contextPtr->oPtr->command) {
	Tcl_DeleteCommandFromToken(interp, contextPtr->oPtr->command);







|







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
	Tcl_DeleteCommandFromToken(interp, oPtr->command);
    }
    return TCL_OK;
}

static int
AfterNRDestructor(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];

    if (contextPtr->oPtr->command) {
	Tcl_DeleteCommandFromToken(interp, contextPtr->oPtr->command);
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
 *	Implementation for oo::object->eval method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_Eval(
    TCL_UNUSED(ClientData),
    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);
    CallFrame *framePtr, **framePtrPtr = &framePtr;
    Tcl_Obj *scriptPtr;
    CmdFrame *invoker;

    if (objc-1 < skip) {
	Tcl_WrongNumArgs(interp, skip, objv, "arg ?arg ...?");
	return TCL_ERROR;
    }

    /*
     * Make the object's namespace the current namespace and evaluate the
     * command(s).







|








|




|







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
 *	Implementation for oo::object->eval method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_Eval(
    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);
    size_t skip = Tcl_ObjectContextSkippedArgs(context);
    CallFrame *framePtr, **framePtrPtr = &framePtr;
    Tcl_Obj *scriptPtr;
    CmdFrame *invoker;

    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).
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
     * 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) {
	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[],
    Tcl_Interp *interp,
    int result)
{
    if (result == TCL_ERROR) {
	Object *oPtr = (Object *)data[0];
	const char *namePtr;








|


















|







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
     * 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 ((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(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    if (result == TCL_ERROR) {
	Object *oPtr = (Object *)data[0];
	const char *namePtr;

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
 *	just creates a suitable error message.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_Unknown(
    TCL_UNUSED(ClientData),
    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, 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) {
	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.







|











>
|









|







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
 *	just creates a suitable error message.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_Unknown(
    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;
    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 ((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.
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
	    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);
	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, methodNames[i], -1);
    }
    if (i) {
	Tcl_AppendToObj(errorMsg, " or ", -1);
    }
    Tcl_AppendToObj(errorMsg, methodNames[i], -1);
    Tcl_Free((void *)methodNames);
    Tcl_SetObjResult(interp, errorMsg);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
	    TclGetString(objv[skip]), NULL);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Object_LinkVar --
 *
 *	Implementation of oo::object->variable method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_LinkVar(
    TCL_UNUSED(ClientData),
    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;

    if (objc-Tcl_ObjectContextSkippedArgs(context) < 0) {
	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++) {
	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);
	    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







|


















|















|









|

|















|












|







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
	    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]), (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, methodNames[i], -1);
    }
    if (i) {
	Tcl_AppendToObj(errorMsg, " or ", -1);
    }
    Tcl_AppendToObj(errorMsg, methodNames[i], -1);
    Tcl_Free((void *)methodNames);
    Tcl_SetObjResult(interp, errorMsg);
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "METHOD",
	    TclGetString(objv[skip]), (char *)NULL);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Object_LinkVar --
 *
 *	Implementation of oo::object->variable method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_LinkVar(
    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;
    Tcl_Size i;

    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++) {
	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", (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
	    /*
	     * 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);
	    return TCL_ERROR;
	}

	/*
	 * Arrange for the lifetime of the variable to be correctly managed.
	 * This is copied out of Tcl_VariableObjCmd...
	 */







|







693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
	    /*
	     * 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", (char *)NULL);
	    return TCL_ERROR;
	}

	/*
	 * Arrange for the lifetime of the variable to be correctly managed.
	 * This is copied out of Tcl_VariableObjCmd...
	 */
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
 *	Implementation of the oo::object->varname method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Object_VarName(
    TCL_UNUSED(ClientData),
    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. */
{
    Var *varPtr, *aryVar;
    Tcl_Obj *varNamePtr, *argPtr;
    CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
    const char *arg;

    if (Tcl_ObjectContextSkippedArgs(context)+1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"varName");
	return TCL_ERROR;
    }
    argPtr = objv[objc-1];
    arg = TclGetString(argPtr);








|











|







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
 *	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. */
{
    Var *varPtr, *aryVar;
    Tcl_Obj *varNamePtr, *argPtr;
    CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
    const char *arg;

    if ((int)Tcl_ObjectContextSkippedArgs(context)+1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"varName");
	return TCL_ERROR;
    }
    argPtr = objv[objc-1];
    arg = TclGetString(argPtr);

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787

	if (framePtr->isProcCallFrame & FRAME_IS_METHOD) {
	    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
	    CallContext *callerContext = (CallContext *)framePtr->clientData;
	    Method *mPtr = callerContext->callPtr->chain[
		    callerContext->index].mPtr;
	    PrivateVariableMapping *pvPtr;
	    int i;

	    if (mPtr->declaringObjectPtr == oPtr) {
		FOREACH_STRUCT(pvPtr, oPtr->privateVariables) {
		    if (!strcmp(TclGetString(pvPtr->variableObj),
			    TclGetString(argPtr))) {
			argPtr = pvPtr->fullNameObj;
			break;







|







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790

	if (framePtr->isProcCallFrame & FRAME_IS_METHOD) {
	    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
	    CallContext *callerContext = (CallContext *)framePtr->clientData;
	    Method *mPtr = callerContext->callPtr->chain[
		    callerContext->index].mPtr;
	    PrivateVariableMapping *pvPtr;
	    Tcl_Size i;

	    if (mPtr->declaringObjectPtr == oPtr) {
		FOREACH_STRUCT(pvPtr, oPtr->privateVariables) {
		    if (!strcmp(TclGetString(pvPtr->variableObj),
			    TclGetString(argPtr))) {
			argPtr = pvPtr->fullNameObj;
			break;
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
	Tcl_AppendObjToObj(varNamePtr, argPtr);
    }
    Tcl_IncrRefCount(varNamePtr);
    varPtr = TclObjLookupVar(interp, varNamePtr, NULL,
	    TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to", 1, 1, &aryVar);
    Tcl_DecrRefCount(varNamePtr);
    if (varPtr == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", arg, NULL);
	return TCL_ERROR;
    }

    /*
     * Now that we've pinned down what variable we're really talking about
     * (including traversing variable links), convert back to a name.
     */







|







821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
	Tcl_AppendObjToObj(varNamePtr, argPtr);
    }
    Tcl_IncrRefCount(varNamePtr);
    varPtr = TclObjLookupVar(interp, varNamePtr, NULL,
	    TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG, "refer to", 1, 1, &aryVar);
    Tcl_DecrRefCount(varNamePtr);
    if (varPtr == NULL) {
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARIABLE", arg, (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Now that we've pinned down what variable we're really talking about
     * (including traversing variable links), convert back to a name.
     */
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
 *	method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOONextObjCmd(
    TCL_UNUSED(ClientData),
    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);
	return TCL_ERROR;
    }
    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_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *framePtr = iPtr->varFramePtr;
    Class *classPtr;
    CallContext *contextPtr;
    int 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);
	return TCL_ERROR;
    }
    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;
    if (classPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"%s\" is not a class", TclGetString(objv[1])));
	Tcl_SetErrorCode(interp, "TCL", "OO", "CLASS_REQUIRED", 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!







|


















|
















|








|













|




















|







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
 *	method.
 *
 * ----------------------------------------------------------------------
 */

int
TclOONextObjCmd(
    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", (char *)NULL);
	return TCL_ERROR;
    }
    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(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *framePtr = iPtr->varFramePtr;
    Class *classPtr;
    CallContext *contextPtr;
    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", (char *)NULL);
	return TCL_ERROR;
    }
    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;
    if (classPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"%s\" is not a class", TclGetString(objv[1])));
	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!
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
	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;

	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);
	    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);
    return TCL_ERROR;
}

static int
NextRestoreFrame(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    CallContext *contextPtr = (CallContext *)data[1];

    iPtr->varFramePtr = (CallFrame *)data[0];
    if (contextPtr != NULL) {
	contextPtr->index = PTR2INT(data[2]);
    }
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOSelfObjCmd --
 *
 *	Implementation of the [self] command, which provides introspection of
 *	the call context.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOSelfObjCmd(
    TCL_UNUSED(ClientData),
    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
    };
    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);
	return TCL_ERROR;
    }

    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) {
    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));
	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);
	    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);
	    return TCL_ERROR;
	} else {
	    struct MInvoke *miPtr = &CurrentlyInvoked(contextPtr);
	    Object *oPtr;
	    const char *type;

	    if (miPtr->filterDeclarer != NULL) {







|







|






|





|








|

















|











|




<












|




















|





|







|




















|







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
	methodType = "constructor";
    } else if (contextPtr->callPtr->flags & DESTRUCTOR) {
	methodType = "destructor";
    } else {
	methodType = "method";
    }

    for (i=contextPtr->index ; i != TCL_INDEX_NONE ; i--) {
	struct 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",
		    (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", (char *)NULL);
    return TCL_ERROR;
}

static int
NextRestoreFrame(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Interp *iPtr = (Interp *) interp;
    CallContext *contextPtr = (CallContext *)data[1];

    iPtr->varFramePtr = (CallFrame *)data[0];
    if (contextPtr != NULL) {
	contextPtr->index = PTR2UINT(data[2]);
    }
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOSelfObjCmd --
 *
 *	Implementation of the [self] command, which provides introspection of
 *	the call context.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOSelfObjCmd(
    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];


#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", (char *)NULL);
	return TCL_ERROR;
    }

    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 (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));
	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", (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", (char *)NULL);
	    return TCL_ERROR;
	} else {
	    struct MInvoke *miPtr = &CurrentlyInvoked(contextPtr);
	    Object *oPtr;
	    const char *type;

	    if (miPtr->filterDeclarer != NULL) {
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
	    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);
	    return TCL_ERROR;
	} else {
	    CallContext *callerPtr = (CallContext *)framePtr->callerVarPtr->clientData;
	    Method *mPtr = callerPtr->callPtr->chain[callerPtr->index].mPtr;
	    Object *declarerPtr;

	    if (mPtr->declaringClassPtr != NULL) {







|







1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
	    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", (char *)NULL);
	    return TCL_ERROR;
	} else {
	    CallContext *callerPtr = (CallContext *)framePtr->callerVarPtr->clientData;
	    Method *mPtr = callerPtr->callPtr->chain[callerPtr->index].mPtr;
	    Object *declarerPtr;

	    if (mPtr->declaringClassPtr != NULL) {
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
	    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);
	    return TCL_ERROR;
	} else {
	    Method *mPtr;
	    Object *declarerPtr;
	    int i;

	    for (i=contextPtr->index ; i<contextPtr->callPtr->numChain ; i++){
		if (!contextPtr->callPtr->chain[i].isFilter) {
		    break;
		}
	    }
	    if (i == contextPtr->callPtr->numChain) {







|




|







1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
	    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", (char *)NULL);
	    return TCL_ERROR;
	} else {
	    Method *mPtr;
	    Object *declarerPtr;
	    Tcl_Size i;

	    for (i=contextPtr->index ; i<contextPtr->callPtr->numChain ; i++){
		if (!contextPtr->callPtr->chain[i].isFilter) {
		    break;
		}
	    }
	    if (i == contextPtr->callPtr->numChain) {
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
	    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);
	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_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?");
	return TCL_ERROR;
    }

    oPtr = Tcl_GetObjectFromObj(interp, objv[1]);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }







|




















|








|







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
	    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);
	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(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?");
	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
/*
 * tclOOCall.c --
 *
 *	This file contains the method call chain management code for the
 *	object-system core.

 *
 * Copyright (c) 2005-2012 by 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.
 */

struct ChainBuilder {
    CallChain *callChainPtr;	/* The call chain being built. */
    int 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. */
};

/*




|
>

|



















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * tclOOCall.c --
 *
 *	This file contains the method call chain management code for the
 *	object-system core. It also contains everything else that does
 *	inheritance hierarchy traversal.
 *
 * 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.
 */

struct ChainBuilder {
    CallChain *callChainPtr;	/* The call chain being built. */
    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. */
};

/*
54
55
56
57
58
59
60

61
62
63
64
65
66
67
#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

#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.







>







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#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
#define 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.
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
 * Function declarations for things defined in this file.
 */

static void		AddClassFiltersToCallContext(Object *const oPtr,
			    Class *clsPtr, struct ChainBuilder *const cbPtr,
			    Tcl_HashTable *const doneFilters, int flags);
static void		AddClassMethodNames(Class *clsPtr, const 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,







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
 * Function declarations for things defined in this file.
 */

static void		AddClassFiltersToCallContext(Object *const oPtr,
			    Class *clsPtr, struct ChainBuilder *const cbPtr,
			    Tcl_HashTable *const doneFilters, 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,
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
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,
			    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

};


/*
 * ----------------------------------------------------------------------
 *
 * TclOODeleteContext --







|












|
>







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
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 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,
    TCL_OBJTYPE_V0
};


/*
 * ----------------------------------------------------------------------
 *
 * TclOODeleteContext --
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
 */

static inline void
StashCallChain(
    Tcl_Obj *objPtr,
    CallChain *callPtr)
{
    Tcl_ObjIntRep ir;

    callPtr->refCount++;
    TclGetString(objPtr);
    ir.twoPtrValue.ptr1 = callPtr;
    Tcl_StoreIntRep(objPtr, &methodNameType, &ir);
}

void
TclOOStashContext(
    Tcl_Obj *objPtr,
    CallContext *contextPtr)
{







|




|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
 */

static inline void
StashCallChain(
    Tcl_Obj *objPtr,
    CallChain *callPtr)
{
    Tcl_ObjInternalRep ir;

    callPtr->refCount++;
    TclGetString(objPtr);
    ir.twoPtrValue.ptr1 = callPtr;
    Tcl_StoreInternalRep(objPtr, &methodNameType, &ir);
}

void
TclOOStashContext(
    Tcl_Obj *objPtr,
    CallContext *contextPtr)
{
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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

static void
DupMethodNameRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dstPtr)
{
    StashCallChain(dstPtr,
	    (CallChain *)TclFetchIntRep(srcPtr, &methodNameType)->twoPtrValue.ptr1);
}

static void
FreeMethodNameRep(
    Tcl_Obj *objPtr)
{
    TclOODeleteChain(
	    (CallChain *)TclFetchIntRep(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. */
    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;
    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;

	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







|







|

















|



















|







279
280
281
282
283
284
285
286
287
288
289
290
291
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

static void
DupMethodNameRep(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dstPtr)
{
    StashCallChain(dstPtr,
	    (CallChain *)TclFetchInternalRep(srcPtr, &methodNameType)->twoPtrValue.ptr1);
}

static void
FreeMethodNameRep(
    Tcl_Obj *objPtr)
{
    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(
    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;
    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) {
	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
	contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    }

    /*
     * Run the method implementation.
     */


    return mPtr->typePtr->callProc(mPtr->clientData, interp,



	    (Tcl_ObjectContext) contextPtr, objc, objv);
}

static int
SetFilterFlags(
    ClientData data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];

    contextPtr->oPtr->flags |= FILTER_HANDLING;
    return result;
}

static int
ResetFilterFlags(
    ClientData data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];

    contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    return result;
}

static int
FinalizeMethodRefs(
    ClientData data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];
    int i;

    for (i = 0 ; i < contextPtr->callPtr->numChain ; i++) {
	TclOODelMethodRef(contextPtr->callPtr->chain[i].mPtr);
    }
    return result;
}








>
|
>
>
>





|











|











|




|







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
	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,
		(Tcl_ObjectContext) contextPtr, objc, objv);
    }
    return ((Tcl_MethodCallProc2 *)(void *)(mPtr->typePtr->callProc))(mPtr->clientData, interp,
	    (Tcl_ObjectContext) contextPtr, objc, objv);
}

static int
SetFilterFlags(
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];

    contextPtr->oPtr->flags |= FILTER_HANDLING;
    return result;
}

static int
ResetFilterFlags(
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    CallContext *contextPtr = (CallContext *)data[0];

    contextPtr->oPtr->flags &= ~FILTER_HANDLING;
    return result;
}

static int
FinalizeMethodRefs(
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    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
    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;
    Class *mixinPtr;
    Tcl_Obj *namePtr;
    Method *mPtr;

    Tcl_InitObjHashTable(&names);
    Tcl_InitHashTable(&examinedClasses, TCL_ONE_WORD_KEYS);








|







448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
    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;
    Tcl_Size i, numStrings;
    Class *mixinPtr;
    Tcl_Obj *namePtr;
    Method *mPtr;

    Tcl_InitObjHashTable(&names);
    Tcl_InitHashTable(&examinedClasses, TCL_ONE_WORD_KEYS);

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

    Tcl_DeleteHashTable(&examinedClasses);
    numStrings = SortMethodNames(&names, flags, stringsPtr);
    Tcl_DeleteHashTable(&names);
    return numStrings;
}

int
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;

    Tcl_InitObjHashTable(&names);
    Tcl_InitHashTable(&examinedClasses, TCL_ONE_WORD_KEYS);

    /*
     * Process method names from the class hierarchy and the mixin hierarchy.
     */







|













|







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

    Tcl_DeleteHashTable(&examinedClasses);
    numStrings = SortMethodNames(&names, flags, stringsPtr);
    Tcl_DeleteHashTable(&names);
    return numStrings;
}

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. */
    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
 *
 * Returns:
 *	The length of the sorted list.
 *
 * ----------------------------------------------------------------------
 */

static int
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. */







|







583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
 *
 * Returns:
 *	The length of the sorted list.
 *
 * ----------------------------------------------------------------------
 */

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. */
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
 *
 * ----------------------------------------------------------------------
 */

static void
AddClassMethodNames(
    Class *clsPtr,		/* Class to get method names from. */
    const 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;

    /*
     * If we've already started looking at this class, stop working on it now
     * to prevent repeated work.
     */

    if (Tcl_FindHashEntry(examinedClassesPtr, (char *) 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,
		&isNew);
	if (!isNew) {
	    break;
	}

	if (clsPtr->mixins.num != 0) {
	    Class *mixinPtr;







|














|






|
















|







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
 *
 * ----------------------------------------------------------------------
 */

static void
AddClassMethodNames(
    Class *clsPtr,		/* Class to get method names from. */
    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. */
{
    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, 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, 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
    Method *mPtr;
    Tcl_Obj *namePtr;

    FOREACH_HASH(namePtr, mPtr, methodsTablePtr) {
	if (IS_PRIVATE(mPtr)) {
	    int isNew;

	    hPtr = Tcl_CreateHashEntry(namesPtr, (char *) 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);

	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));







|















|







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
    Method *mPtr;
    Tcl_Obj *namePtr;

    FOREACH_HASH(namePtr, mPtr, methodsTablePtr) {
	if (IS_PRIVATE(mPtr)) {
	    int 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, 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));
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
    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);
	if (hPtr != NULL) {
	    mPtr = (Method *)Tcl_GetHashValue(hPtr);
	    if (IS_PRIVATE(mPtr)) {
		AddMethodToCallChain(mPtr, cbPtr, NULL, NULL, flags);
		donePrivate = 1;
	    }
	}







|







836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
    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, methodName);
	if (hPtr != NULL) {
	    mPtr = (Method *)Tcl_GetHashValue(hPtr);
	    if (IS_PRIVATE(mPtr)) {
		AddMethodToCallChain(mPtr, cbPtr, NULL, NULL, flags);
		donePrivate = 1;
	    }
	}
873
874
875
876
877
878
879

880
881
882
883
884
885
886
887
888
889
890
891
892
				/* 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, foundPrivate = 0, blockedUnexported = 0;
    Tcl_HashEntry *hPtr;
    Method *mPtr;

    if (!(flags & (KNOWN_STATE | SPECIAL)) && oPtr->methodsPtr) {
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) methodNameObj);

	if (hPtr != NULL) {
	    mPtr = (Method *)Tcl_GetHashValue(hPtr);
	    if (!IS_PRIVATE(mPtr)) {
		if (WANT_PUBLIC(flags)) {
		    if (!IS_PUBLIC(mPtr)) {
			blockedUnexported = 1;







>
|




|







880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
				/* 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 foundPrivate = 0, blockedUnexported = 0;
    Tcl_HashEntry *hPtr;
    Method *mPtr;

    if (!(flags & (KNOWN_STATE | SPECIAL)) && oPtr->methodsPtr) {
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, methodNameObj);

	if (hPtr != NULL) {
	    mPtr = (Method *)Tcl_GetHashValue(hPtr);
	    if (!IS_PRIVATE(mPtr)) {
		if (WANT_PUBLIC(flags)) {
		    if (!IS_PUBLIC(mPtr)) {
			blockedUnexported = 1;
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
			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);
	    if (hPtr != NULL) {
		mPtr = (Method *)Tcl_GetHashValue(hPtr);
		if (!IS_PRIVATE(mPtr)) {
		    AddMethodToCallChain(mPtr, cbPtr, doneFilters, filterDecl,
			    flags);
		}
	    }







|







917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
			doneFilters, flags|TRAVERSED_MIXIN, filterDecl);
	    }
	    foundPrivate |= AddSimpleClassChainToCallContext(mixinPtr,
		    methodNameObj, cbPtr, doneFilters,
		    flags | TRAVERSED_MIXIN, filterDecl);
	}
	if (oPtr->methodsPtr && !blockedUnexported) {
	    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, methodNameObj);
	    if (hPtr != NULL) {
		mPtr = (Method *)Tcl_GetHashValue(hPtr);
		if (!IS_PRIVATE(mPtr)) {
		    AddMethodToCallChain(mPtr, cbPtr, doneFilters, filterDecl,
			    flags);
		}
	    }
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
				 * 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;

    /*
     * 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.







|







973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
				 * 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;
    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.
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
 * 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
 *	- No public/private/filter magic leakage (same flags, modulo the fact
 *	  that a public chain will satisfy a non-public call).
 *
 * ----------------------------------------------------------------------
 */

static inline int







|







1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
 * 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 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
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157
1158
1159
    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;
    Tcl_HashEntry *hPtr;
    Tcl_HashTable doneFilters;

    if (cacheInThisObj == NULL) {
	cacheInThisObj = methodNameObj;
    }
    if (flags&(SPECIAL|FILTER_HANDLING) || (oPtr->flags&FILTER_HANDLING)) {







>
|







1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
    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;
    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
	/*
	 * 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 int reuseMask = (WANT_PUBLIC(flags) ? ~0 : ~PUBLIC_METHOD);

	if ((irPtr = TclFetchIntRep(cacheInThisObj, &methodNameType))) {
	    callPtr = (CallChain *)irPtr->twoPtrValue.ptr1;
	    if (IsStillValid(callPtr, oPtr, flags, reuseMask)) {
		callPtr->refCount++;
		goto returnContext;
	    }
	    Tcl_StoreIntRep(cacheInThisObj, &methodNameType, NULL);
	}

	if (oPtr->flags & USE_CLASS_CACHE) {
	    if (oPtr->selfCls->classChainCache != NULL) {
		hPtr = Tcl_FindHashEntry(oPtr->selfCls->classChainCache,
			(char *) methodNameObj);
	    } else {
		hPtr = NULL;
	    }
	} else {
	    if (oPtr->chainCache != NULL) {
		hPtr = Tcl_FindHashEntry(oPtr->chainCache,
			(char *) methodNameObj);
	    } else {
		hPtr = NULL;
	    }
	}

	if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) {
	    callPtr = (CallChain *)Tcl_GetHashValue(hPtr);







|


|





|





|






|







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
	/*
	 * 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_ObjInternalRep *irPtr;
	const int reuseMask = (WANT_PUBLIC(flags) ? ~0 : ~PUBLIC_METHOD);

	if ((irPtr = TclFetchInternalRep(cacheInThisObj, &methodNameType))) {
	    callPtr = (CallChain *)irPtr->twoPtrValue.ptr1;
	    if (IsStillValid(callPtr, oPtr, flags, reuseMask)) {
		callPtr->refCount++;
		goto returnContext;
	    }
	    Tcl_StoreInternalRep(cacheInThisObj, &methodNameType, NULL);
	}

	if (oPtr->flags & USE_CLASS_CACHE) {
	    if (oPtr->selfCls->classChainCache != NULL) {
		hPtr = Tcl_FindHashEntry(oPtr->selfCls->classChainCache,
			methodNameObj);
	    } else {
		hPtr = NULL;
	    }
	} else {
	    if (oPtr->chainCache != NULL) {
		hPtr = Tcl_FindHashEntry(oPtr->chainCache,
			methodNameObj);
	    } else {
		hPtr = NULL;
	    }
	}

	if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) {
	    callPtr = (CallChain *)Tcl_GetHashValue(hPtr);
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
	callPtr->epoch = 0;
	if (count == callPtr->numChain) {
	    TclOODeleteChain(callPtr);
	    return NULL;
	}
    } else if (doFilters && !donePrivate) {
	if (hPtr == NULL) {

	    if (oPtr->flags & USE_CLASS_CACHE) {
		if (oPtr->selfCls->classChainCache == NULL) {
		    oPtr->selfCls->classChainCache =
			    (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));

		    Tcl_InitObjHashTable(oPtr->selfCls->classChainCache);
		}
		hPtr = Tcl_CreateHashEntry(oPtr->selfCls->classChainCache,
			(char *) methodNameObj, &i);
	    } else {
		if (oPtr->chainCache == NULL) {
		    oPtr->chainCache = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));

		    Tcl_InitObjHashTable(oPtr->chainCache);
		}
		hPtr = Tcl_CreateHashEntry(oPtr->chainCache,
			(char *) methodNameObj, &i);
	    }
	}
	callPtr->refCount++;
	Tcl_SetHashValue(hPtr, callPtr);
	StashCallChain(cacheInThisObj, callPtr);
    } else if (flags & CONSTRUCTOR) {
	if (oPtr->selfCls->constructorChainPtr) {







>








|







|







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
	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));

		    Tcl_InitObjHashTable(oPtr->selfCls->classChainCache);
		}
		hPtr = Tcl_CreateHashEntry(oPtr->selfCls->classChainCache,
			methodNameObj, &isNew);
	    } else {
		if (oPtr->chainCache == NULL) {
		    oPtr->chainCache = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));

		    Tcl_InitObjHashTable(oPtr->chainCache);
		}
		hPtr = Tcl_CreateHashEntry(oPtr->chainCache,
			methodNameObj, &isNew);
	    }
	}
	callPtr->refCount++;
	Tcl_SetHashValue(hPtr, callPtr);
	StashCallChain(cacheInThisObj, callPtr);
    } else if (flags & CONSTRUCTOR) {
	if (oPtr->selfCls->constructorChainPtr) {
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
    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;
    Foundation *fPtr = clsPtr->thisPtr->fPtr;
    Tcl_HashEntry *hPtr;
    Tcl_HashTable doneFilters;
    Object obj;

    /*
     * Synthesize a temporary stereotypical object so that we can use existing







|







1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
    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;
    Tcl_Size count;
    Foundation *fPtr = clsPtr->thisPtr->fPtr;
    Tcl_HashEntry *hPtr;
    Tcl_HashTable doneFilters;
    Object obj;

    /*
     * Synthesize a temporary stereotypical object so that we can use existing
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
     * 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);
	if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) {
	    const int reuseMask = (WANT_PUBLIC(flags) ? ~0 : ~PUBLIC_METHOD);

	    callPtr = (CallChain *)Tcl_GetHashValue(hPtr);
	    if (IsStillValid(callPtr, &obj, flags, reuseMask)) {
		callPtr->refCount++;
		return callPtr;







|







1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
     * 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,
		methodNameObj);
	if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) {
	    const int reuseMask = (WANT_PUBLIC(flags) ? ~0 : ~PUBLIC_METHOD);

	    callPtr = (CallChain *)Tcl_GetHashValue(hPtr);
	    if (IsStillValid(callPtr, &obj, flags, reuseMask)) {
		callPtr->refCount++;
		return callPtr;
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
	    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).
     */

    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) {

	    if (clsPtr->classChainCache == NULL) {
		clsPtr->classChainCache = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
		Tcl_InitObjHashTable(clsPtr->classChainCache);
	    }
	    hPtr = Tcl_CreateHashEntry(clsPtr->classChainCache,
		    (char *) methodNameObj, &i);
	}
	callPtr->refCount++;
	Tcl_SetHashValue(hPtr, callPtr);
	StashCallChain(methodNameObj, callPtr);
    }
    return callPtr;
}







|















>





|







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
	    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
     * 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));
		Tcl_InitObjHashTable(clsPtr->classChainCache);
	    }
	    hPtr = Tcl_CreateHashEntry(clsPtr->classChainCache,
		    methodNameObj, &isNew);
	}
	callPtr->refCount++;
	Tcl_SetHashValue(hPtr, callPtr);
	StashCallChain(methodNameObj, callPtr);
    }
    return callPtr;
}
1538
1539
1540
1541
1542
1543
1544

1545
1546
1547
1548
1549
1550
1551
1552
    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. */
{

    int i, clearedFlags =
	    flags & ~(TRAVERSED_MIXIN|OBJECT_MIXIN|BUILDING_MIXINS);
    Class *superPtr, *mixinPtr;
    Tcl_Obj *filterObj;

  tailRecurse:
    if (clsPtr == NULL) {
	return;







>
|







1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
    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 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
     * override how filters work to extend their behaviour.
     */

    if (MIXIN_CONSISTENT(flags)) {
	FOREACH(filterObj, clsPtr->filters) {
	    int isNew;

	    (void) Tcl_CreateHashEntry(doneFilters, (char *) filterObj,
		    &isNew);
	    if (isNew) {
		AddSimpleChainToCallContext(oPtr, NULL, filterObj, cbPtr,
			doneFilters, clearedFlags|BUILDING_MIXINS, clsPtr);
		AddSimpleChainToCallContext(oPtr, NULL, filterObj, cbPtr,
			doneFilters, clearedFlags, clsPtr);
	    }
	}







|
<







1580
1581
1582
1583
1584
1585
1586
1587

1588
1589
1590
1591
1592
1593
1594
     * override how filters work to extend their behaviour.
     */

    if (MIXIN_CONSISTENT(flags)) {
	FOREACH(filterObj, clsPtr->filters) {
	    int isNew;

	    (void) Tcl_CreateHashEntry(doneFilters, filterObj, &isNew);

	    if (isNew) {
		AddSimpleChainToCallContext(oPtr, NULL, filterObj, cbPtr,
			doneFilters, clearedFlags|BUILDING_MIXINS, clsPtr);
		AddSimpleChainToCallContext(oPtr, NULL, filterObj, cbPtr,
			doneFilters, clearedFlags, clsPtr);
	    }
	}
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
				/* 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;
    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.







|







1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
				/* 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;
    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.
1705
1706
1707
1708
1709
1710
1711

1712
1713
1714
1715
1716
1717
1718
1719
				/* 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, 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.







>
|







1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
				/* 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 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.
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
	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);

	if (classPtr->flags & HAS_PRIVATE_METHODS) {
	    privateDanger |= 1;
	}
	if (hPtr != NULL) {
	    Method *mPtr = (Method *)Tcl_GetHashValue(hPtr);








|







1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
	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,
		methodNameObj);

	if (classPtr->flags & HAS_PRIVATE_METHODS) {
	    privateDanger |= 1;
	}
	if (hPtr != NULL) {
	    Method *mPtr = (Method *)Tcl_GetHashValue(hPtr);

1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
TclOORenderCallChain(
    Tcl_Interp *interp,
    CallChain *callPtr)
{
    Tcl_Obj *filterLiteral, *methodLiteral, *objectLiteral, *privateLiteral;
    Tcl_Obj *resultObj, *descObjs[4], **objv;
    Foundation *fPtr = TclOOGetFoundation(interp);
    int i;

    /*
     * Allocate the literals (potentially) used in our description.
     */

    TclNewLiteralStringObj(filterLiteral, "filter");
    Tcl_IncrRefCount(filterLiteral);







|







1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
TclOORenderCallChain(
    Tcl_Interp *interp,
    CallChain *callPtr)
{
    Tcl_Obj *filterLiteral, *methodLiteral, *objectLiteral, *privateLiteral;
    Tcl_Obj *resultObj, *descObjs[4], **objv;
    Foundation *fPtr = TclOOGetFoundation(interp);
    Tcl_Size i;

    /*
     * Allocate the literals (potentially) used in our description.
     */

    TclNewLiteralStringObj(filterLiteral, "filter");
    Tcl_IncrRefCount(filterLiteral);
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
				 * [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;

    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);

    /*
     * Go through the list until we find a namespace whose name we can
     * resolve.
     */

    FOREACH_STRUCT(entryPtr, define) {







|










|
|







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
				 * [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, 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, 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
    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;

    FOREACH(mixinPtr, oPtr->mixins) {
	AddSimpleClassDefineNamespaces(mixinPtr, definePtr,
		flags | TRAVERSED_MIXIN);
    }

    AddSimpleClassDefineNamespaces(oPtr->selfCls, definePtr, flags);







|







1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
    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;
    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
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;
    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)) {
	AddDefinitionNamespaceToChain(classPtr, classPtr->clsDefinitionNs,
		definePtr, flags);
    } else {
	AddDefinitionNamespaceToChain(classPtr, classPtr->objDefinitionNs,
		definePtr, flags);
    }








|













|







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
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. */
{
    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 & DEFINE_FOR_CLASS) {
	AddDefinitionNamespaceToChain(classPtr, classPtr->clsDefinitionNs,
		definePtr, flags);
    } else {
	AddDefinitionNamespaceToChain(classPtr, classPtr->objDefinitionNs,
		definePtr, flags);
    }

2097
2098
2099
2100
2101
2102
2103





























































































































































































































































2104
2105
2106
2107
2108
2109
2110
2111
		    sizeof(DefineEntry) * definePtr->size);
	}
    }
    definePtr->list[i].definerCls = definerCls;
    definePtr->list[i].namespaceName = namespaceName;
    definePtr->num++;
}






























































































































































































































































/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








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
		    sizeof(DefineEntry) * definePtr->size);
	}
    }
    definePtr->list[i].definerCls = definerCls;
    definePtr->list[i].namespaceName = namespaceName;
    definePtr->num++;
}

/*
 * ----------------------------------------------------------------------
 *
 * 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);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetAllClassProperties --
 *
 *	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.
 *
 * ----------------------------------------------------------------------
 */

Tcl_Obj *
TclOOGetAllClassProperties(
    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;
    void *dummy;

    /*
     * 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(propName, dummy, &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;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOGetAllObjectProperties --
 *
 *	Get the list of all properties known to a object, including to its
 *	classes. Manages a cache so this operation is usually cheap.
 *	The order of properties in the resulting list is undefined.
 *
 * ----------------------------------------------------------------------
 */

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. */
    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;
    void *dummy;

    /*
     * Look in the cache.
     */

    if (oPtr->properties.epoch == oPtr->fPtr->epoch) {
	if (writable) {
	    if (oPtr->properties.allWritableCache) {
		*allocated = 0;
		return oPtr->properties.allWritableCache;
	    }
	} else {
	    if (oPtr->properties.allReadableCache) {
		*allocated = 0;
		return oPtr->properties.allReadableCache;
	    }
	}
    }

    /*
     * Gather the information. Unsorted! (Caller will sort.)
     */

    *allocated = 1;
    Tcl_InitObjHashTable(&hashTable);
    FindObjectProps(oPtr, writable, &hashTable);
    TclNewObj(result);
    FOREACH_HASH(propName, dummy, &hashTable) {
	Tcl_ListObjAppendElement(NULL, result, propName);
    }
    Tcl_DeleteHashTable(&hashTable);

    /*
     * 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;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

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
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);
/* 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(
				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);
/* 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);




















typedef struct {
    const struct TclOOIntStubs *tclOOIntStubs;
} TclOOStubHooks;

typedef struct TclOOStubs {
    int magic;







|
|










|

















|
|

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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, 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 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, 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
    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 */
    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 */
    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 */
    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 */





} TclOOStubs;

extern const TclOOStubs *tclOOStubsPtr;

#ifdef __cplusplus
}
#endif







|




|




|






>
>
>
>
>







155
156
157
158
159
160
161
162
163
164
165
166
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, 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 */
    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, 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
	(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 */











#endif /* defined(USE_TCLOO_STUBS) */

/* !END!: Do not edit above this line. */











#endif /* _TCLOODECLS */







>
>
>
>
>
>
>
>
>
>





>
>
>
>
>
>
>
>
>
>

251
252
253
254
255
256
257
258
259
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
/*
 * 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
 *
 * 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"






|







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 © 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"
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138








139
140
141
142
143
144
145
#define PUBLIC_PATTERN		"[a-z]*"

/*
 * Forward declarations.
 */

static inline void	BumpGlobalEpoch(Tcl_Interp *interp, Class *classPtr);

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,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassFilterSet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassMixinGet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassMixinSet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassSuperGet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassSuperSet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassVarsGet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,



			    int objc, Tcl_Obj *const *objv);
static int		ClassVarsSet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjFilterGet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjFilterSet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjMixinGet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjMixinSet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjVarsGet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjVarsSet(ClientData clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);


static int		ResolveClass(ClientData 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),








    {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().
 */







>


















|


|


|


|


|


|


|

>
>
>

|
<
|
|


|


|


|


|


|


>
>
|















>
>
>
>
>
>
>
>







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#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(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassFilterSet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassMixinGet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassMixinSet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassSuperGet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassSuperSet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassVarsGet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassVarsSet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static Tcl_MethodCallProc ClassRPropsGet, ClassRPropsSet;

static Tcl_MethodCallProc ClassWPropsGet, ClassWPropsSet;
static int		ObjFilterGet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjFilterSet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjMixinGet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjMixinSet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjVarsGet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ObjVarsSet(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static Tcl_MethodCallProc ObjRPropsGet, ObjRPropsSet;
static Tcl_MethodCallProc ObjWPropsGet, ObjWPropsSet;
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),
    SLOT("configuresupport::readableproperties",
	    ClassRPropsGet, ClassRPropsSet, NULL),
    SLOT("configuresupport::writableproperties",
	    ClassWPropsGet, ClassWPropsSet, NULL),
    SLOT("configuresupport::objreadableproperties",
	    ObjRPropsGet, ObjRPropsSet, NULL),
    SLOT("configuresupport::objwritableproperties",
	    ObjWPropsGet, ObjWPropsSet, 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
	 * 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++;













	}
	return;
    }

    /*
     * Either there's no class (?!) or we're reconfiguring something that is
     * in use. Force regeneration of call chains.
     */

    TclOOGetFoundation(interp)->epoch++;
}




























/*
 * ----------------------------------------------------------------------
 *
 * RecomputeClassCacheFlag --
 *
 *	Determine whether the object is prototypical of its class, and hence







>
>
>
>
>
>
>
>
>
>
>
>
>






|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
	 * 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 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
 *
 * ----------------------------------------------------------------------
 */

void
TclOOObjectSetFilters(
    Object *oPtr,
    int numFilters,
    Tcl_Obj *const *filters)
{
    int i;

    if (oPtr->filters.num) {
	Tcl_Obj *filterObj;

	FOREACH(filterObj, oPtr->filters) {
	    Tcl_DecrRefCount(filterObj);
	}







|


|







298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
 *
 * ----------------------------------------------------------------------
 */

void
TclOOObjectSetFilters(
    Object *oPtr,
    Tcl_Size numFilters,
    Tcl_Obj *const *filters)
{
    Tcl_Size i;

    if (oPtr->filters.num) {
	Tcl_Obj *filterObj;

	FOREACH(filterObj, oPtr->filters) {
	    Tcl_DecrRefCount(filterObj);
	}
288
289
290
291
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
	    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. */
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOClassSetFilters --
 *
 *	Install a list of filter method names into a class.
 *
 * ----------------------------------------------------------------------
 */

void
TclOOClassSetFilters(
    Tcl_Interp *interp,
    Class *classPtr,
    int numFilters,
    Tcl_Obj *const *filters)
{
    int i;

    if (classPtr->filters.num) {
	Tcl_Obj *filterObj;

	FOREACH(filterObj, classPtr->filters) {
	    Tcl_DecrRefCount(filterObj);
	}







|
















|


|







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
	    filtersList[i] = filters[i];
	    Tcl_IncrRefCount(filters[i]);
	}
	oPtr->filters.list = filtersList;
	oPtr->filters.num = numFilters;
	oPtr->flags &= ~USE_CLASS_CACHE;
    }
    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,
    Tcl_Size numFilters,
    Tcl_Obj *const *filters)
{
    Tcl_Size i;

    if (classPtr->filters.num) {
	Tcl_Obj *filterObj;

	FOREACH(filterObj, classPtr->filters) {
	    Tcl_DecrRefCount(filterObj);
	}
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
 *
 * ----------------------------------------------------------------------
 */

void
TclOOObjectSetMixins(
    Object *oPtr,
    int numMixins,
    Class *const *mixins)
{
    Class *mixinPtr;
    int i;

    if (numMixins == 0) {
	if (oPtr->mixins.num != 0) {
	    FOREACH(mixinPtr, oPtr->mixins) {
		TclOORemoveFromInstances(oPtr, mixinPtr);
		TclOODecrRefCount(mixinPtr->thisPtr);
	    }







|



|







420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
 *
 * ----------------------------------------------------------------------
 */

void
TclOOObjectSetMixins(
    Object *oPtr,
    Tcl_Size numMixins,
    Class *const *mixins)
{
    Class *mixinPtr;
    Tcl_Size i;

    if (numMixins == 0) {
	if (oPtr->mixins.num != 0) {
	    FOREACH(mixinPtr, oPtr->mixins) {
		TclOORemoveFromInstances(oPtr, mixinPtr);
		TclOODecrRefCount(mixinPtr->thisPtr);
	    }
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
		 * For the new copy created by memcpy().
		 */

		AddRef(mixinPtr->thisPtr);
	    }
	}
    }
    oPtr->epoch++;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOClassSetMixins --
 *
 *	Install a list of mixin classes into a class.
 *
 * ----------------------------------------------------------------------
 */

void
TclOOClassSetMixins(
    Tcl_Interp *interp,
    Class *classPtr,
    int numMixins,
    Class *const *mixins)
{
    Class *mixinPtr;
    int i;

    if (numMixins == 0) {
	if (classPtr->mixins.num != 0) {
	    FOREACH(mixinPtr, classPtr->mixins) {
		TclOORemoveFromMixinSubs(classPtr, mixinPtr);
		TclOODecrRefCount(mixinPtr->thisPtr);
	    }







|
















|



|







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
		 * For the new copy created by memcpy().
		 */

		AddRef(mixinPtr->thisPtr);
	    }
	}
    }
    BumpInstanceEpoch(oPtr);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOClassSetMixins --
 *
 *	Install a list of mixin classes into a class.
 *
 * ----------------------------------------------------------------------
 */

void
TclOOClassSetMixins(
    Tcl_Interp *interp,
    Class *classPtr,
    Tcl_Size numMixins,
    Class *const *mixins)
{
    Class *mixinPtr;
    Tcl_Size i;

    if (numMixins == 0) {
	if (classPtr->mixins.num != 0) {
	    FOREACH(mixinPtr, classPtr->mixins) {
		TclOORemoveFromMixinSubs(classPtr, mixinPtr);
		TclOODecrRefCount(mixinPtr->thisPtr);
	    }
478
479
480
481
482
483
484

485
486
487
488
489
490
491

492
493
494
495
496
497
498
499
 *
 * InstallStandardVariableMapping, InstallPrivateVariableMapping --
 *
 *	Helpers for installing standard and private variable maps.
 *
 * ----------------------------------------------------------------------
 */

static inline void
InstallStandardVariableMapping(
    VariableNameList *vnlPtr,
    int varc,
    Tcl_Obj *const *varv)
{
    Tcl_Obj *variableObj;

    int i, n, created;
    Tcl_HashTable uniqueTable;

    for (i=0 ; i<varc ; i++) {
	Tcl_IncrRefCount(varv[i]);
    }
    FOREACH(variableObj, *vnlPtr) {
	Tcl_DecrRefCount(variableObj);







>



|



>
|







531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
 *
 * InstallStandardVariableMapping, InstallPrivateVariableMapping --
 *
 *	Helpers for installing standard and private variable maps.
 *
 * ----------------------------------------------------------------------
 */

static inline void
InstallStandardVariableMapping(
    VariableNameList *vnlPtr,
    Tcl_Size varc,
    Tcl_Obj *const *varv)
{
    Tcl_Obj *variableObj;
    Tcl_Size i, n;
    int created;
    Tcl_HashTable uniqueTable;

    for (i=0 ; i<varc ; i++) {
	Tcl_IncrRefCount(varv[i]);
    }
    FOREACH(variableObj, *vnlPtr) {
	Tcl_DecrRefCount(variableObj);
530
531
532
533
534
535
536
537
538
539
540
541

542
543
544
545
546
547
548
549
	Tcl_DeleteHashTable(&uniqueTable);
    }
}

static inline void
InstallPrivateVariableMapping(
    PrivateVariableList *pvlPtr,
    int varc,
    Tcl_Obj *const *varv,
    int creationEpoch)
{
    PrivateVariableMapping *privatePtr;

    int i, n, created;
    Tcl_HashTable uniqueTable;

    for (i=0 ; i<varc ; i++) {
	Tcl_IncrRefCount(varv[i]);
    }
    FOREACH_STRUCT(privatePtr, *pvlPtr) {
	Tcl_DecrRefCount(privatePtr->variableObj);







|




>
|







585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
	Tcl_DeleteHashTable(&uniqueTable);
    }
}

static inline void
InstallPrivateVariableMapping(
    PrivateVariableList *pvlPtr,
    Tcl_Size varc,
    Tcl_Obj *const *varv,
    int creationEpoch)
{
    PrivateVariableMapping *privatePtr;
    Tcl_Size i, n;
    int created;
    Tcl_HashTable uniqueTable;

    for (i=0 ; i<varc ; i++) {
	Tcl_IncrRefCount(varv[i]);
    }
    FOREACH_STRUCT(privatePtr, *pvlPtr) {
	Tcl_DecrRefCount(privatePtr->variableObj);
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

    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);
	    return TCL_ERROR;
	}
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) fromPtr);
	if (hPtr == NULL) {
	    goto noSuchMethod;
	}
	if (toPtr) {
	    newHPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) 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);
		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);
		return TCL_ERROR;
	    }
	}
    } else {
	hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods,
		(char *) fromPtr);
	if (hPtr == NULL) {
	    goto noSuchMethod;
	}
	if (toPtr) {
	    newHPtr = Tcl_CreateHashEntry(&oPtr->classPtr->classMethods,
		    (char *) toPtr, &isNew);
	    if (hPtr == newHPtr) {







|


|




|





|






|




|
<







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

    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), (char *)NULL);
	    return TCL_ERROR;
	}
	hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, fromPtr);
	if (hPtr == NULL) {
	    goto noSuchMethod;
	}
	if (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", (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", (char *)NULL);
		return TCL_ERROR;
	    }
	}
    } else {
	hPtr = Tcl_FindHashEntry(&oPtr->classPtr->classMethods, fromPtr);

	if (hPtr == NULL) {
	    goto noSuchMethod;
	}
	if (toPtr) {
	    newHPtr = Tcl_CreateHashEntry(&oPtr->classPtr->classMethods,
		    (char *) toPtr, &isNew);
	    if (hPtr == newHPtr) {
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
 *	prefix of.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOUnknownDefinition(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Namespace *nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_HashSearch search;
    Tcl_HashEntry *hPtr;
    size_t soughtLen;
    const char *soughtStr, *matchedStr = NULL;

    if (objc < 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"bad call of unknown handler", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_UNKNOWN", NULL);
	return TCL_ERROR;
    }
    if (TclOOGetDefineCmdContext(interp) == NULL) {
	return TCL_ERROR;
    }

    soughtStr = TclGetStringFromObj(objv[1], &soughtLen);







|







|





|







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
 *	prefix of.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOUnknownDefinition(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Namespace *nsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
    Tcl_HashSearch search;
    Tcl_HashEntry *hPtr;
    Tcl_Size soughtLen;
    const char *soughtStr, *matchedStr = NULL;

    if (objc < 2) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"bad call of unknown handler", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_UNKNOWN", (char *)NULL);
	return TCL_ERROR;
    }
    if (TclOOGetDefineCmdContext(interp) == NULL) {
	return TCL_ERROR;
    }

    soughtStr = TclGetStringFromObj(objv[1], &soughtLen);
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
	TclStackFree(interp, newObjv);
	return result;
    }

  noMatch:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "invalid command name \"%s\"", soughtStr));
    Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", soughtStr, 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;
    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.







|




















|







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
	TclStackFree(interp, newObjv);
	return result;
    }

  noMatch:
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
	    "invalid command name \"%s\"", soughtStr));
    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)
{
    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.
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
    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);
	return TCL_ERROR;
    }

    /*
     * framePtrPtr is needed to satisfy GCC 3.3's strict aliasing rules.
     */








|







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
    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", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * framePtrPtr is needed to satisfy GCC 3.3's strict aliasing rules.
     */

883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905

    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);
	return NULL;
    }
    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);
	return NULL;
    }
    return object;
}

/*
 * ----------------------------------------------------------------------







|







|







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->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", (char *)NULL);
	return NULL;
    }
    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", (char *)NULL);
	return NULL;
    }
    return object;
}

/*
 * ----------------------------------------------------------------------
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
    iPtr->varFramePtr = savedFramePtr;
    if (oPtr == NULL) {
	return NULL;
    }
    if (oPtr->classPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
		TclGetString(className), NULL);
	return NULL;
    }
    return oPtr->classPtr;
}

static inline Tcl_Namespace *
GetNamespaceInOuterContext(







|







990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
    iPtr->varFramePtr = savedFramePtr;
    if (oPtr == NULL) {
	return NULL;
    }
    if (oPtr->classPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(errMsg, -1));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "CLASS",
		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
				 * 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_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 overflow = (length > limit);

    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (in definition script for %s \"%.*s%s\" line %d)",
	    typeOfSubject, (overflow ? limit : (unsigned)length), objName,
	    (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
}

/*
 * ----------------------------------------------------------------------
 *
 * MagicDefinitionInvoke --







|



|




|







1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
				 * 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. */
{
    Tcl_Size length;
    Tcl_Obj *realNameObj = Tcl_ObjectDeleted((Tcl_Object) oPtr)
	    ? savedNameObj : TclOOObjectName(interp, oPtr);
    const char *objName = TclGetStringFromObj(realNameObj, &length);
    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 : (int)length), objName,
	    (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
}

/*
 * ----------------------------------------------------------------------
 *
 * MagicDefinitionInvoke --
1028
1029
1030
1031
1032
1033
1034
1035

1036
1037
1038
1039
1040
1041
1042
    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;


    /*
     * 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







|
>







1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
    Tcl_Namespace *nsPtr,
    int cmdIndex,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *objPtr, *obj2Ptr, **objs;
    Tcl_Command cmd;
    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
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
	Tcl_AppendObjToObj(obj2Ptr, objv[cmdIndex]);
    } else {
	Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
    }
    Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
    /* TODO: overflow? */
    Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc - offset, objv + offset);
    Tcl_ListObjGetElements(NULL, objPtr, &dummy, &objs);

    result = Tcl_EvalObjv(interp, objc - cmdIndex, objs, TCL_EVAL_INVOKE);
    if (isRoot) {
	TclResetRewriteEnsemble(interp, 1);
    }
    Tcl_DecrRefCount(objPtr);








|







1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
	Tcl_AppendObjToObj(obj2Ptr, objv[cmdIndex]);
    } else {
	Tcl_GetCommandFullName(interp, cmd, obj2Ptr);
    }
    Tcl_ListObjAppendElement(NULL, objPtr, obj2Ptr);
    /* TODO: overflow? */
    Tcl_ListObjReplace(NULL, objPtr, 1, 0, objc - offset, objv + offset);
    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
 *	messages are clearer.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Namespace *nsPtr;
    Object *oPtr;
    int result;







|







1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
 *	messages are clearer.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineObjCmd(
    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
    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);
	return TCL_ERROR;
    }

    /*
     * Make the oo::define namespace the current namespace and evaluate the
     * command(s).
     */







|







1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
    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]), (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Make the oo::define namespace the current namespace and evaluate the
     * command(s).
     */
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
 *	messages are clearer.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOObjDefObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Namespace *nsPtr;
    Object *oPtr;
    int result;







|







1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
 *	messages are clearer.
 *
 * ----------------------------------------------------------------------
 */

int
TclOOObjDefObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Namespace *nsPtr;
    Object *oPtr;
    int result;
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
 *	dispatch so that error messages are clearer.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineSelfObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Namespace *nsPtr;
    Object *oPtr;
    int result, isPrivate;







|







1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
 *	dispatch so that error messages are clearer.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineSelfObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Namespace *nsPtr;
    Object *oPtr;
    int result, isPrivate;
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineObjSelfObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr;

    if (objc != 1) {







|







1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineObjSelfObjCmd(
    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
 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefinePrivateObjCmd(
    ClientData 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







|







1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefinePrivateObjCmd(
    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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineClassObjCmd(
    TCL_UNUSED(ClientData),
    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);
	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);
	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);
	return TCL_ERROR;
    }

    /*
     * Set the object's class.
     */








|




















|





|



















|







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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineClassObjCmd(
    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", (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", (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", (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
	} else if (!wasClass && willBeClass) {
	    TclOOAllocClass(interp, oPtr);
	}

	if (oPtr->classPtr != NULL) {
	    BumpGlobalEpoch(interp, oPtr->classPtr);
	} else {
	    oPtr->epoch++;
	}
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineConstructorObjCmd --
 *
 *	Implementation of the "constructor" subcommand of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineConstructorObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr;
    Class *clsPtr;
    Tcl_Method method;
    size_t bodyLength;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "arguments body");
	return TCL_ERROR;
    }

    /*







|


















|







|







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
	} else if (!wasClass && willBeClass) {
	    TclOOAllocClass(interp, oPtr);
	}

	if (oPtr->classPtr != NULL) {
	    BumpGlobalEpoch(interp, oPtr->classPtr);
	} else {
	    BumpInstanceEpoch(oPtr);
	}
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineConstructorObjCmd --
 *
 *	Implementation of the "constructor" subcommand of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineConstructorObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr;
    Class *clsPtr;
    Tcl_Method method;
    Tcl_Size bodyLength;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "arguments body");
	return TCL_ERROR;
    }

    /*
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
 *	"oo::define" command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineDefnNsObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    static const char *kindList[] = {
	"-class",
	"-instance",







|







1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
 *	"oo::define" command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineDefnNsObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    static const char *kindList[] = {
	"-class",
	"-instance",
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == 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)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not modify the definition namespace of the root classes",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    }

    /*
     * Parse the arguments and work out what the user wants to do.
     */








|






|







1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    if (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    }
    if (oPtr->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", (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Parse the arguments and work out what the user wants to do.
     */

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
 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineDeleteMethodObjCmd(
    ClientData 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);
	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++;
    } 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_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr;
    Class *clsPtr;
    Tcl_Method method;
    size_t bodyLength;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "body");
	return TCL_ERROR;
    }

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);







|




















|















|



















|







|







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
 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineDeleteMethodObjCmd(
    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", (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) {
	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(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr;
    Class *clsPtr;
    Tcl_Method method;
    Tcl_Size bodyLength;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "body");
	return TCL_ERROR;
    }

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
 *	"oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineExportObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceExport = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;







|







1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
 *	"oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineExportObjCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceExport = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;
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
    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);
	return TCL_ERROR;
    }

    for (i = 1; i < objc; i++) {
	/*
	 * Exporting is done by adding the PUBLIC_METHOD flag to the method
	 * record. If there is no such method in this object or class (i.e.
	 * the method comes from something inherited from or that we're an
	 * instance of) then we put in a blank record with that flag; such
	 * records are skipped over by the call chain engine *except* for
	 * their flags member.
	 */

	if (isInstanceExport) {
	    if (!oPtr->methodsPtr) {
		oPtr->methodsPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
		Tcl_InitObjHashTable(oPtr->methodsPtr);
		oPtr->flags &= ~USE_CLASS_CACHE;
	    }
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *)objv[i],
		    &isNew);
	} else {
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)objv[i],
		    &isNew);
	}

	if (isNew) {
	    mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	    memset(mPtr, 0, sizeof(Method));
	    mPtr->refCount = 1;







|



















|


|







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
    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", (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));
		Tcl_InitObjHashTable(oPtr->methodsPtr);
		oPtr->flags &= ~USE_CLASS_CACHE;
	    }
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, objv[i],
		    &isNew);
	} else {
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, objv[i],
		    &isNew);
	}

	if (isNew) {
	    mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	    memset(mPtr, 0, sizeof(Method));
	    mPtr->refCount = 1;
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

    /*
     * Bump the right epoch if we actually changed anything.
     */

    if (changed) {
	if (isInstanceExport) {
	    oPtr->epoch++;
	} 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,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceForward = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;







|




















|







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

    /*
     * Bump the right epoch if we actually changed anything.
     */

    if (changed) {
	if (isInstanceExport) {
	    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(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceForward = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
    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);
	return TCL_ERROR;
    }
    isPublic = Tcl_StringMatch(TclGetString(objv[1]), PUBLIC_PATTERN)
	    ? PUBLIC_METHOD : 0;
    if (IsPrivateDefine(interp)) {
	isPublic = TRUE_PRIVATE_METHOD;
    }







|







1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
    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", (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
 *	"oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineMethodObjCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    /*
     * Table of export modes for methods and their corresponding enum.
     */







|







2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 *	"oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineMethodObjCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    /*
     * Table of export modes for methods and their corresponding enum.
     */
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
    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);
	return TCL_ERROR;
    }
    if (objc == 5) {
	if (Tcl_GetIndexFromObj(interp, objv[2], exportModes, "export flag",
		0, (int *) &exportMode) != TCL_OK) {
	    return TCL_ERROR;
	}
	switch (exportMode) {
	case MODE_EXPORT:
	    isPublic = PUBLIC_METHOD;
	    break;
	case MODE_PRIVATE:







|




|







2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
    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", (char *)NULL);
	return TCL_ERROR;
    }
    if (objc == 5) {
	if (Tcl_GetIndexFromObj(interp, objv[2], exportModes, "export flag",
		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
 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineRenameMethodObjCmd(
    ClientData 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);
	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++;
    } 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,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceUnexport = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;







|



















|
















|



















|







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
 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineRenameMethodObjCmd(
    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", (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) {
	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(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceUnexport = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;
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
    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);
	return TCL_ERROR;
    }

    for (i = 1; i < objc; i++) {
	/*
	 * Unexporting is done by removing the PUBLIC_METHOD flag from the
	 * method record. If there is no such method in this object or class
	 * (i.e. the method comes from something inherited from or that we're
	 * an instance of) then we put in a blank record without that flag;
	 * such records are skipped over by the call chain engine *except* for
	 * their flags member.
	 */

	if (isInstanceUnexport) {
	    if (!oPtr->methodsPtr) {
		oPtr->methodsPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
		Tcl_InitObjHashTable(oPtr->methodsPtr);
		oPtr->flags &= ~USE_CLASS_CACHE;
	    }
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *)objv[i],
		    &isNew);
	} else {
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)objv[i],
		    &isNew);
	}

	if (isNew) {
	    mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	    memset(mPtr, 0, sizeof(Method));
	    mPtr->refCount = 1;







|



















|


|







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
    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", (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));
		Tcl_InitObjHashTable(oPtr->methodsPtr);
		oPtr->flags &= ~USE_CLASS_CACHE;
	    }
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, objv[i],
		    &isNew);
	} else {
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, objv[i],
		    &isNew);
	}

	if (isNew) {
	    mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	    memset(mPtr, 0, sizeof(Method));
	    mPtr->refCount = 1;
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197

    /*
     * Bump the right epoch if we actually changed anything.
     */

    if (changed) {
	if (isInstanceUnexport) {
	    oPtr->epoch++;
	} else {
	    BumpGlobalEpoch(interp, clsPtr);
	}
    }
    return TCL_OK;
}








|







2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253

    /*
     * Bump the right epoch if we actually changed anything.
     */

    if (changed) {
	if (isInstanceUnexport) {
	    BumpInstanceEpoch(oPtr);
	} else {
	    BumpGlobalEpoch(interp, clsPtr);
	}
    }
    return TCL_OK;
}

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
    const struct DeclaredSlot *slotInfoPtr;
    Tcl_Obj *getName = Tcl_NewStringObj("Get", -1);
    Tcl_Obj *setName = Tcl_NewStringObj("Set", -1);
    Tcl_Obj *resolveName = Tcl_NewStringObj("Resolve", -1);
    Class *slotCls;

    slotCls = ((Object *) Tcl_NewObjectInstance(fPtr->interp, (Tcl_Class)
	    fPtr->classCls, "::oo::Slot", NULL, -1, NULL, 0))->classPtr;
    if (slotCls == NULL) {
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(getName);
    Tcl_IncrRefCount(setName);
    Tcl_IncrRefCount(resolveName);
    for (slotInfoPtr = slots ; slotInfoPtr->name ; slotInfoPtr++) {
	Tcl_Object slotObject = Tcl_NewObjectInstance(fPtr->interp,
		(Tcl_Class) slotCls, slotInfoPtr->name, NULL, -1, NULL, 0);

	if (slotObject == NULL) {
	    continue;
	}
	Tcl_NewInstanceMethod(fPtr->interp, slotObject, getName, 0,
		&slotInfoPtr->getterType, NULL);
	Tcl_NewInstanceMethod(fPtr->interp, slotObject, setName, 0,
		&slotInfoPtr->setterType, NULL);
	if (slotInfoPtr->resolverType.callProc) {
	    Tcl_NewInstanceMethod(fPtr->interp, slotObject, resolveName, 0,
		    &slotInfoPtr->resolverType, NULL);
	}
    }
    Tcl_DecrRefCount(getName);
    Tcl_DecrRefCount(setName);
    Tcl_DecrRefCount(resolveName);
    return TCL_OK;







|








|




|

|


|







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
    const struct DeclaredSlot *slotInfoPtr;
    Tcl_Obj *getName = Tcl_NewStringObj("Get", -1);
    Tcl_Obj *setName = Tcl_NewStringObj("Set", -1);
    Tcl_Obj *resolveName = Tcl_NewStringObj("Resolve", -1);
    Class *slotCls;

    slotCls = ((Object *) Tcl_NewObjectInstance(fPtr->interp, (Tcl_Class)
	    fPtr->classCls, "::oo::Slot", NULL, TCL_INDEX_NONE, NULL, 0))->classPtr;
    if (slotCls == NULL) {
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(getName);
    Tcl_IncrRefCount(setName);
    Tcl_IncrRefCount(resolveName);
    for (slotInfoPtr = slots ; slotInfoPtr->name ; slotInfoPtr++) {
	Tcl_Object slotObject = Tcl_NewObjectInstance(fPtr->interp,
		(Tcl_Class) slotCls, slotInfoPtr->name, NULL, TCL_INDEX_NONE, NULL, 0);

	if (slotObject == NULL) {
	    continue;
	}
	TclNewInstanceMethod(fPtr->interp, slotObject, getName, 0,
		&slotInfoPtr->getterType, NULL);
	TclNewInstanceMethod(fPtr->interp, slotObject, setName, 0,
		&slotInfoPtr->setterType, NULL);
	if (slotInfoPtr->resolverType.callProc) {
	    TclNewInstanceMethod(fPtr->interp, slotObject, resolveName, 0,
		    &slotInfoPtr->resolverType, NULL);
	}
    }
    Tcl_DecrRefCount(getName);
    Tcl_DecrRefCount(setName);
    Tcl_DecrRefCount(resolveName);
    return TCL_OK;
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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassFilterGet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj, *filterObj;
    int i;

    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) {
	Tcl_ListObjAppendElement(NULL, resultObj, filterObj);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassFilterSet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int filterc;
    Tcl_Obj **filterv;

    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,
	    &filterv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOClassSetFilters(interp, oPtr->classPtr, filterc, filterv);
    return TCL_OK;
}







|







|











|













|






|














|

|







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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassFilterGet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj, *filterObj;
    Tcl_Size i;

    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", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(filterObj, oPtr->classPtr->filters) {
	Tcl_ListObjAppendElement(NULL, resultObj, filterObj);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassFilterSet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Size filterc;
    Tcl_Obj **filterv;

    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", (char *)NULL);
	return TCL_ERROR;
    } else if (TclListObjGetElements(interp, objv[0], &filterc,
	    &filterv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOClassSetFilters(interp, oPtr->classPtr, filterc, filterv);
    return TCL_OK;
}
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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassMixinGet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    Class *mixinPtr;
    int i;

    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) {
	Tcl_ListObjAppendElement(NULL, resultObj,
		TclOOObjectName(interp, mixinPtr->thisPtr));
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;

}

static int
ClassMixinSet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int mixinc, i;
    Tcl_Obj **mixinv;
    Class **mixins;






    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,
	    &mixinv) != TCL_OK) {
	return TCL_ERROR;
    }

    mixins = (Class **)TclStackAlloc(interp, sizeof(Class *) * mixinc);


    for (i = 0; i < mixinc; i++) {
	mixins[i] = GetClassInOuterContext(interp, mixinv[i],
		"may only mix in classes");
	if (mixins[i] == NULL) {
	    i--;
	    goto freeAndError;







	}
	if (TclOOIsReachable(oPtr->classPtr, mixins[i])) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "may not mix a class into itself", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", NULL);
	    goto freeAndError;
	}
    }

    TclOOClassSetMixins(interp, oPtr->classPtr, mixinc, mixins);

    TclStackFree(interp, mixins);
    return TCL_OK;

  freeAndError:

    TclStackFree(interp, mixins);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * ClassSuperGet, ClassSuperSet --
 *
 *	Implementation of the "superclass" slot accessors of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassSuperGet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    Class *superPtr;
    int i;

    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) {
	Tcl_ListObjAppendElement(NULL, resultObj,
		TclOOObjectName(interp, superPtr->thisPtr));
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassSuperSet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int superc, i, j;

    Tcl_Obj **superv;
    Class **superclasses, *superPtr;

    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"superclassList");
	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 (oPtr == oPtr->fPtr->objectCls->thisPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not modify the superclass of the root object", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL);
	return TCL_ERROR;
    } else if (Tcl_ListObjGetElements(interp, objv[0], &superc,
	    &superv) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Allocate some working space.
     */







|








|











|















|






|

|
>
>
>
>
>













|

|





>







>
>
>
>
>
>
>




|





>




>

















|








|











|














|






|
>















|




|

|







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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassMixinGet(
    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;
    Tcl_Size i;

    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", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(mixinPtr, oPtr->classPtr->mixins) {
	Tcl_ListObjAppendElement(NULL, resultObj,
		TclOOObjectName(interp, mixinPtr->thisPtr));
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;

}

static int
ClassMixinSet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Size mixinc, i;
    Tcl_Obj **mixinv;
    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;
    }
    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", (char *)NULL);
	return TCL_ERROR;
    } else if (TclListObjGetElements(interp, objv[0], &mixinc,
	    &mixinv) != TCL_OK) {
	return TCL_ERROR;
    }

    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", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "REPETITIOUS", (char *)NULL);
	    goto freeAndError;
	}
	if (TclOOIsReachable(oPtr->classPtr, mixins[i])) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "may not mix a class into itself", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", (char *)NULL);
	    goto freeAndError;
	}
    }

    TclOOClassSetMixins(interp, oPtr->classPtr, mixinc, mixins);
    Tcl_DeleteHashTable(&uniqueCheck);
    TclStackFree(interp, mixins);
    return TCL_OK;

  freeAndError:
    Tcl_DeleteHashTable(&uniqueCheck);
    TclStackFree(interp, mixins);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * ClassSuperGet, ClassSuperSet --
 *
 *	Implementation of the "superclass" slot accessors of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassSuperGet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    Class *superPtr;
    Tcl_Size i;

    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", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(superPtr, oPtr->classPtr->superclasses) {
	Tcl_ListObjAppendElement(NULL, resultObj,
		TclOOObjectName(interp, superPtr->thisPtr));
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassSuperSet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Size superc, j;
    Tcl_Size i;
    Tcl_Obj **superv;
    Class **superclasses, *superPtr;

    if (Tcl_ObjectContextSkippedArgs(context) + 1 != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		"superclassList");
	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", (char *)NULL);
	return TCL_ERROR;
    } else if (oPtr == oPtr->fPtr->objectCls->thisPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"may not modify the superclass of the root object", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    } else if (TclListObjGetElements(interp, objv[0], &superc,
	    &superv) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * Allocate some working space.
     */
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
		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);
		    goto failedAfterAlloc;
		}
	    }
	    if (TclOOIsReachable(oPtr->classPtr, superclasses[i])) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"attempt to form circular dependency graph", -1));
		Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL);
	    failedAfterAlloc:
		for (; i-- > 0 ;) {
		    TclOODecrRefCount(superclasses[i]->thisPtr);
		}
		Tcl_Free(superclasses);
		return TCL_ERROR;
	    }







|






|







2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
		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",(char *)NULL);
		    goto failedAfterAlloc;
		}
	    }
	    if (TclOOIsReachable(oPtr->classPtr, superclasses[i])) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"attempt to form circular dependency graph", -1));
		Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", (char *)NULL);
	    failedAfterAlloc:
		for (; i-- > 0 ;) {
		    TclOODecrRefCount(superclasses[i]->thisPtr);
		}
		Tcl_Free(superclasses);
		return TCL_ERROR;
	    }
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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassVarsGet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    int i;

    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;








|







|











|







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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ClassVarsGet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    Tcl_Size i;

    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", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    if (IsPrivateDefine(interp)) {
	PrivateVariableMapping *privatePtr;

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
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassVarsSet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);

    int varc;
    Tcl_Obj **varv;
    int i;

    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,
	    &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);
	    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);
	    return TCL_ERROR;
	}
    }

    if (IsPrivateDefine(interp)) {
	InstallPrivateVariableMapping(&oPtr->classPtr->privateVariables,
		varc, varv, oPtr->classPtr->thisPtr->creationEpoch);







|






>
|

<













|

|











|






|







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
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassVarsSet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Size i;
    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 (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    } else if (TclListObjGetElements(interp, objv[0], &varc,
	    &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", (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", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    if (IsPrivateDefine(interp)) {
	InstallPrivateVariableMapping(&oPtr->classPtr->privateVariables,
		varc, varv, oPtr->classPtr->thisPtr->creationEpoch);
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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ObjFilterGet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj, *filterObj;
    int 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),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int 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,
	    &filterv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOObjectSetFilters(oPtr, filterc, filterv);
    return TCL_OK;
}







|







|



















|






|










|







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
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ObjFilterGet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj, *filterObj;
    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(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    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 (TclListObjGetElements(interp, objv[0], &filterc,
	    &filterv) != TCL_OK) {
	return TCL_ERROR;
    }

    TclOOObjectSetFilters(oPtr, filterc, filterv);
    return TCL_OK;
}
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ObjMixinGet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    Class *mixinPtr;
    int i;

    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    } else if (oPtr == NULL) {
	return TCL_ERROR;







|








|







2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ObjMixinGet(
    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;
    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;
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
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ObjMixinSet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int mixinc;
    Tcl_Obj **mixinv;
    Class **mixins;




    int i;

    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,
	    &mixinv) != TCL_OK) {
	return TCL_ERROR;
    }

    mixins = (Class **)TclStackAlloc(interp, sizeof(Class *) * mixinc);


    for (i = 0; i < mixinc; i++) {
	mixins[i] = GetClassInOuterContext(interp, mixinv[i],
		"may only mix in classes");
	if (mixins[i] == NULL) {




	    TclStackFree(interp, mixins);


	    return TCL_ERROR;
	}
    }

    TclOOObjectSetMixins(oPtr, mixinc, mixins);
    TclStackFree(interp, mixins);

    return TCL_OK;





}

/*
 * ----------------------------------------------------------------------
 *
 * ObjectVarsGet, ObjectVarsSet --
 *
 *	Implementation of the "variable" slot accessors of the "oo::objdefine"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ObjVarsGet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    int i;

    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    } else if (oPtr == NULL) {
	return TCL_ERROR;







|






|

|
>
>
>
>
|









|





>





>
>
>
>
|
>
>
|





>

>
>
>
>
>















|







|







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
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ObjMixinSet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Size mixinc, i;
    Tcl_Obj **mixinv;
    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 (TclListObjGetElements(interp, objv[0], &mixinc,
	    &mixinv) != TCL_OK) {
	return TCL_ERROR;
    }

    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) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "class should only be a direct mixin once", -1));
	    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 --
 *
 *	Implementation of the "variable" slot accessors of the "oo::objdefine"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

static int
ObjVarsGet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj;
    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;
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
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ObjVarsSet(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    int 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,
	    &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);
	    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);
	    return TCL_ERROR;
	}
    }

    if (IsPrivateDefine(interp)) {
	InstallPrivateVariableMapping(&oPtr->privateVariables, varc, varv,
		oPtr->creationEpoch);







|






|










|











|






|







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
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ObjVarsSet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    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 (TclListObjGetElements(interp, objv[0], &varc,
	    &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", (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", (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
 *	names to their fully-qualified names if possible.
 *
 * ----------------------------------------------------------------------
 */

static int
ResolveClass(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    int idx = Tcl_ObjectContextSkippedArgs(context);
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);







|







3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
 *	names to their fully-qualified names if possible.
 *
 * ----------------------------------------------------------------------
 */

static int
ResolveClass(
    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
	Tcl_SetObjResult(interp, objv[idx]);
    } else {
	Tcl_SetObjResult(interp, TclOOObjectName(interp, clsPtr->thisPtr));
    }

    return TCL_OK;
}











































































































































































































































































































































































































/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








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
	Tcl_SetObjResult(interp, objv[idx]);
    } else {
	Tcl_SetObjResult(interp, TclOOObjectName(interp, clsPtr->thisPtr));
    }

    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * ClassRPropsGet, ClassRPropsSet, ObjRPropsGet, ObjRPropsSet --
 *
 *	Implementations of the "readableproperties" slot accessors for classes
 *	and instances.
 *
 * ----------------------------------------------------------------------
 */

static void
InstallReadableProps(
    PropertyStorage *props,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *propObj;
    Tcl_Size i, n;
    int created;
    Tcl_HashTable uniqueTable;

    if (props->allReadableCache) {
	Tcl_DecrRefCount(props->allReadableCache);
	props->allReadableCache = NULL;
    }

    for (i=0 ; i<objc ; i++) {
	Tcl_IncrRefCount(objv[i]);
    }
    FOREACH(propObj, props->readable) {
	Tcl_DecrRefCount(propObj);
    }
    if (i != objc) {
	if (objc == 0) {
	    Tcl_Free(props->readable.list);
	} else if (i) {
	    props->readable.list = (Tcl_Obj **)Tcl_Realloc(props->readable.list,
		    sizeof(Tcl_Obj *) * objc);
	} else {
	    props->readable.list = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj *) * objc);
	}
    }
    props->readable.num = 0;
    if (objc > 0) {
	Tcl_InitObjHashTable(&uniqueTable);
	for (i=n=0 ; i<objc ; i++) {
	    Tcl_CreateHashEntry(&uniqueTable, objv[i], &created);
	    if (created) {
		props->readable.list[n++] = objv[i];
	    } else {
		Tcl_DecrRefCount(objv[i]);
	    }
	}
	props->readable.num = n;

	/*
	 * Shouldn't be necessary, but maintain num/list invariant.
	 */

	if (n != objc) {
	    props->readable.list = (Tcl_Obj **)Tcl_Realloc(props->readable.list,
		    sizeof(Tcl_Obj *) * n);
	}
	Tcl_DeleteHashTable(&uniqueTable);
    }
}

static int
ClassRPropsGet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj, *propNameObj;
    int i;

    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", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(propNameObj, oPtr->classPtr->properties.readable) {
	Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassRPropsSet(
    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 (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    } else if (Tcl_ListObjGetElements(interp, objv[0], &varc,
	    &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    InstallReadableProps(&oPtr->classPtr->properties, varc, varv);
    BumpGlobalEpoch(interp, oPtr->classPtr);
    return TCL_OK;
}

static int
ObjRPropsGet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj, *propNameObj;
    int i;

    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(propNameObj, oPtr->properties.readable) {
	Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ObjRPropsSet(
    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 (Tcl_ListObjGetElements(interp, objv[0], &varc,
	    &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    InstallReadableProps(&oPtr->properties, varc, varv);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * ClassWPropsGet, ClassWPropsSet, ObjWPropsGet, ObjWPropsSet --
 *
 *	Implementations of the "writableproperties" slot accessors for classes
 *	and instances.
 *
 * ----------------------------------------------------------------------
 */

static void
InstallWritableProps(
    PropertyStorage *props,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *propObj;
    Tcl_Size i, n;
    int created;
    Tcl_HashTable uniqueTable;

    if (props->allWritableCache) {
	Tcl_DecrRefCount(props->allWritableCache);
	props->allWritableCache = NULL;
    }

    for (i=0 ; i<objc ; i++) {
	Tcl_IncrRefCount(objv[i]);
    }
    FOREACH(propObj, props->writable) {
	Tcl_DecrRefCount(propObj);
    }
    if (i != objc) {
	if (objc == 0) {
	    Tcl_Free(props->writable.list);
	} else if (i) {
	    props->writable.list = (Tcl_Obj **)Tcl_Realloc(props->writable.list,
		    sizeof(Tcl_Obj *) * objc);
	} else {
	    props->writable.list = (Tcl_Obj **)Tcl_Alloc(sizeof(Tcl_Obj *) * objc);
	}
    }
    props->writable.num = 0;
    if (objc > 0) {
	Tcl_InitObjHashTable(&uniqueTable);
	for (i=n=0 ; i<objc ; i++) {
	    Tcl_CreateHashEntry(&uniqueTable, objv[i], &created);
	    if (created) {
		props->writable.list[n++] = objv[i];
	    } else {
		Tcl_DecrRefCount(objv[i]);
	    }
	}
	props->writable.num = n;

	/*
	 * Shouldn't be necessary, but maintain num/list invariant.
	 */

	if (n != objc) {
	    props->writable.list = (Tcl_Obj **)Tcl_Realloc(props->writable.list,
		    sizeof(Tcl_Obj *) * n);
	}
	Tcl_DeleteHashTable(&uniqueTable);
    }
}

static int
ClassWPropsGet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj, *propNameObj;
    int i;

    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", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(propNameObj, oPtr->classPtr->properties.writable) {
	Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ClassWPropsSet(
    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 (!oPtr->classPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", -1));
	Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", (char *)NULL);
	return TCL_ERROR;
    } else if (Tcl_ListObjGetElements(interp, objv[0], &varc,
	    &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    InstallWritableProps(&oPtr->classPtr->properties, varc, varv);
    BumpGlobalEpoch(interp, oPtr->classPtr);
    return TCL_OK;
}

static int
ObjWPropsGet(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    Tcl_Obj *resultObj, *propNameObj;
    int i;

    if (Tcl_ObjectContextSkippedArgs(context) != objc) {
	Tcl_WrongNumArgs(interp, Tcl_ObjectContextSkippedArgs(context), objv,
		NULL);
	return TCL_ERROR;
    }
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    FOREACH(propNameObj, oPtr->properties.writable) {
	Tcl_ListObjAppendElement(NULL, resultObj, propNameObj);
    }
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
}

static int
ObjWPropsSet(
    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 (Tcl_ListObjGetElements(interp, objv[0], &varc,
	    &varv) != TCL_OK) {
	return TCL_ERROR;
    }

    InstallWritableProps(&oPtr->properties, varc, varv);
    return TCL_OK;
}

/*
 * 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
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
/*
 * tclOODefineCmds.c --
 *
 *	This file contains the implementation of the ::oo-related [info]
 *	subcommands.
 *
 * Copyright (c) 2006-2011 by 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;
static Tcl_ObjCmdProc InfoObjectMethodsCmd;
static Tcl_ObjCmdProc InfoObjectMethodTypeCmd;
static Tcl_ObjCmdProc InfoObjectMixinsCmd;
static Tcl_ObjCmdProc InfoObjectNsCmd;

static Tcl_ObjCmdProc InfoObjectVarsCmd;
static Tcl_ObjCmdProc InfoObjectVariablesCmd;
static Tcl_ObjCmdProc InfoClassCallCmd;
static Tcl_ObjCmdProc InfoClassConstrCmd;
static Tcl_ObjCmdProc InfoClassDefnCmd;
static Tcl_ObjCmdProc InfoClassDefnNsCmd;
static Tcl_ObjCmdProc InfoClassDestrCmd;
static Tcl_ObjCmdProc InfoClassFiltersCmd;
static Tcl_ObjCmdProc InfoClassForwardCmd;
static Tcl_ObjCmdProc InfoClassInstancesCmd;
static Tcl_ObjCmdProc InfoClassMethodsCmd;
static Tcl_ObjCmdProc InfoClassMethodTypeCmd;
static Tcl_ObjCmdProc InfoClassMixinsCmd;

static Tcl_ObjCmdProc InfoClassSubsCmd;
static Tcl_ObjCmdProc InfoClassSupersCmd;
static Tcl_ObjCmdProc InfoClassVariablesCmd;

/*
 * List of commands that are used to implement the [info object] subcommands.
 */

static const EnsembleImplMap infoObjectCmds[] = {
    {"call",	   InfoObjectCallCmd,	    TclCompileBasic2ArgCmd, NULL, NULL, 0},
    {"class",	   InfoObjectClassCmd,	    TclCompileInfoObjectClassCmd, NULL, NULL, 0},
    {"creationid", InfoObjectIdCmd,	    TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"definition", InfoObjectDefnCmd,	    TclCompileBasic2ArgCmd, NULL, NULL, 0},
    {"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},

    {"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.






|












>











>













>




















>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
 * tclOODefineCmds.c --
 *
 *	This file contains the implementation of the ::oo-related [info]
 *	subcommands.
 *
 * 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 void		SortPropList(Tcl_Obj *list);
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;
static Tcl_ObjCmdProc InfoObjectMethodsCmd;
static Tcl_ObjCmdProc InfoObjectMethodTypeCmd;
static Tcl_ObjCmdProc InfoObjectMixinsCmd;
static Tcl_ObjCmdProc InfoObjectNsCmd;
static Tcl_ObjCmdProc InfoObjectPropCmd;
static Tcl_ObjCmdProc InfoObjectVarsCmd;
static Tcl_ObjCmdProc InfoObjectVariablesCmd;
static Tcl_ObjCmdProc InfoClassCallCmd;
static Tcl_ObjCmdProc InfoClassConstrCmd;
static Tcl_ObjCmdProc InfoClassDefnCmd;
static Tcl_ObjCmdProc InfoClassDefnNsCmd;
static Tcl_ObjCmdProc InfoClassDestrCmd;
static Tcl_ObjCmdProc InfoClassFiltersCmd;
static Tcl_ObjCmdProc InfoClassForwardCmd;
static Tcl_ObjCmdProc InfoClassInstancesCmd;
static Tcl_ObjCmdProc InfoClassMethodsCmd;
static Tcl_ObjCmdProc InfoClassMethodTypeCmd;
static Tcl_ObjCmdProc InfoClassMixinsCmd;
static Tcl_ObjCmdProc InfoClassPropCmd;
static Tcl_ObjCmdProc InfoClassSubsCmd;
static Tcl_ObjCmdProc InfoClassSupersCmd;
static Tcl_ObjCmdProc InfoClassVariablesCmd;

/*
 * List of commands that are used to implement the [info object] subcommands.
 */

static const EnsembleImplMap infoObjectCmds[] = {
    {"call",	   InfoObjectCallCmd,	    TclCompileBasic2ArgCmd, NULL, NULL, 0},
    {"class",	   InfoObjectClassCmd,	    TclCompileInfoObjectClassCmd, NULL, NULL, 0},
    {"creationid", InfoObjectIdCmd,	    TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"definition", InfoObjectDefnCmd,	    TclCompileBasic2ArgCmd, NULL, NULL, 0},
    {"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", InfoObjectPropCmd,	    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
    {"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},

    {"subclasses",   InfoClassSubsCmd,		TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
    {"superclasses", InfoClassSupersCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},
    {"variables",    InfoClassVariablesCmd,	TclCompileBasic1Or2ArgCmd, NULL, NULL, 0},
    {NULL, NULL, NULL, NULL, NULL, 0}
};

/*







>







82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
    {"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",   InfoClassPropCmd,		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}
};

/*
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    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);
	return NULL;
    }
    return oPtr->classPtr;
}

/*
 * ----------------------------------------------------------------------







|







154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
    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), (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

    if (objc == 2) {
	Tcl_SetObjResult(interp,
		TclOOObjectName(interp, oPtr->selfCls->thisPtr));
	return TCL_OK;
    } else {
	Class *mixinPtr, *o2clsPtr;
	int i;

	o2clsPtr = GetClassFromObj(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));
		return TCL_OK;
	    }
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		TclOOIsReachable(o2clsPtr, oPtr->selfCls)));
	return TCL_OK;
    }
}

/*
 * ----------------------------------------------------------------------







|











|



|







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

    if (objc == 2) {
	Tcl_SetObjResult(interp,
		TclOOObjectName(interp, oPtr->selfCls->thisPtr));
	return TCL_OK;
    } else {
	Class *mixinPtr, *o2clsPtr;
	Tcl_Size i;

	o2clsPtr = GetClassFromObj(interp, objv[2]);
	if (o2clsPtr == NULL) {
	    return TCL_ERROR;
	}

	FOREACH(mixinPtr, oPtr->mixins) {
	    if (!mixinPtr) {
		continue;
	    }
	    if (TclOOIsReachable(o2clsPtr, mixinPtr)) {
		Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
		return TCL_OK;
	    }
	}
	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
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    if (!oPtr->methodsPtr) {
	goto unknownMethod;
    }
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]);
    if (hPtr == NULL) {
    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));
    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;
    }

    TclNewObj(resultObjs[0]);
    for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {







|





|







|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    if (!oPtr->methodsPtr) {
	goto unknownMethod;
    }
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[2]);
    if (hPtr == NULL) {
    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;
    }
    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]), (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObjs[0]);
    for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
static int
InfoObjectFiltersCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int i;
    Tcl_Obj *filterObj, *resultObj;
    Object *oPtr;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "objName");
	return TCL_ERROR;
    }







|







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
static int
InfoObjectFiltersCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    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
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    if (!oPtr->methodsPtr) {
	goto unknownMethod;
    }
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]);
    if (hPtr == NULL) {
    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;
    }
    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;
    }

    Tcl_SetObjResult(interp, prefixObj);
    return TCL_OK;
}








|





|








|







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
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    if (!oPtr->methodsPtr) {
	goto unknownMethod;
    }
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[2]);
    if (hPtr == NULL) {
    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]), (char *)NULL);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, prefixObj);
    return TCL_OK;
}

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
    Tcl_Obj *const objv[])
{
    static const char *const categories[] = {
	"class", "metaclass", "mixin", "object", "typeof", NULL
    };
    enum IsACats {
	IsClass, IsMetaclass, IsMixin, IsObject, IsType
    };
    Object *oPtr, *o2Ptr;
    int idx, i, result = 0;


    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) {
    case IsObject:
    case IsClass:
    case IsMetaclass:
	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "objName");
	    return TCL_ERROR;
	}







|

|
>















|







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
    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 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 (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
     */

    oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
    if (oPtr == NULL) {
	goto failPrecondition;
    }

    switch ((enum IsACats) idx) {
    case IsObject:
	result = 1;
	break;
    case IsClass:
	result = (oPtr->classPtr != NULL);
	break;
    case IsMetaclass:







|







456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
     */

    oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[2]);
    if (oPtr == NULL) {
	goto failPrecondition;
    }

    switch (idx) {
    case IsObject:
	result = 1;
	break;
    case IsClass:
	result = (oPtr->classPtr != NULL);
	break;
    case IsMetaclass:
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
    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
    };
    static const char *const scopes[] = {
	"private", "public", "unexported"
    };
    enum Scopes {
	SCOPE_PRIVATE, SCOPE_PUBLIC, SCOPE_UNEXPORTED,
	SCOPE_LOCALPRIVATE
    };

    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;

	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) {
	    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);
		    return TCL_ERROR;
		}
		if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0,
			&scope) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;







|

















|






|














|







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
    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
    };

    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;

	for (i=2 ; i<objc ; i++) {
	    if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		    &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    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",
			    (char *)NULL);
		    return TCL_ERROR;
		}
		if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0,
			&scope) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    if (!oPtr->methodsPtr) {
	goto unknownMethod;
    }
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, (char *) objv[2]);
    if (hPtr == NULL) {
    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);
    if (mPtr->typePtr == NULL) {
	/*
	 * Special entry for visibility control: pretend the method doesnt
	 * exist.







|





|







661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
    if (oPtr == NULL) {
	return TCL_ERROR;
    }

    if (!oPtr->methodsPtr) {
	goto unknownMethod;
    }
    hPtr = Tcl_FindHashEntry(oPtr->methodsPtr, objv[2]);
    if (hPtr == NULL) {
    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;
    }
    mPtr = (Method *)Tcl_GetHashValue(hPtr);
    if (mPtr->typePtr == NULL) {
	/*
	 * Special entry for visibility control: pretend the method doesnt
	 * exist.
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *mixinPtr;
    Object *oPtr;
    Tcl_Obj *resultObj;
    int i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "objName");
	return TCL_ERROR;
    }
    oPtr = (Object *) Tcl_GetObjectFromObj(interp, objv[1]);
    if (oPtr == NULL) {







|







704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *mixinPtr;
    Object *oPtr;
    Tcl_Obj *resultObj;
    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) {
805
806
807
808
809
810
811

812
813
814
815
816
817
818
819
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Object *oPtr;
    Tcl_Obj *resultObj;

    int i, 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) {







>
|







811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Object *oPtr;
    Tcl_Obj *resultObj;
    Tcl_Size i;
    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) {
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
    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);
	return TCL_ERROR;
    }

    TclNewObj(resultObjs[0]);
    for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {







|







945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
    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", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObjs[0]);
    for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {
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
	Tcl_WrongNumArgs(interp, 1, objv, "className methodName");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) 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);
	return TCL_ERROR;
    }
    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;
    }

    TclNewObj(resultObjs[0]);
    for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {







|




|







|







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
	Tcl_WrongNumArgs(interp, 1, objv, "className methodName");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    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]), (char *)NULL);
	return TCL_ERROR;
    }
    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]), (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObjs[0]);
    for (localPtr=procPtr->firstLocalPtr; localPtr!=NULL;
	    localPtr=localPtr->nextPtr) {
	if (TclIsVarArgument(localPtr)) {
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
    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);
	return TCL_ERROR;
    }

    Tcl_SetObjResult(interp, TclOOGetMethodBody(clsPtr->destructorPtr));
    return TCL_OK;
}








|







1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
    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", (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
static int
InfoClassFiltersCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    int i;
    Tcl_Obj *filterObj, *resultObj;
    Class *clsPtr;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }







|







1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
static int
InfoClassFiltersCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Size i;
    Tcl_Obj *filterObj, *resultObj;
    Class *clsPtr;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
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
	Tcl_WrongNumArgs(interp, 1, objv, "className methodName");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) 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);
	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;
    }

    Tcl_SetObjResult(interp, prefixObj);
    return TCL_OK;
}








|




|








|







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
	Tcl_WrongNumArgs(interp, 1, objv, "className methodName");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    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]), (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]), (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
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Object *oPtr;
    Class *clsPtr;
    int i;
    const char *pattern = NULL;
    Tcl_Obj *resultObj;

    if (objc != 2 && objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?pattern?");
	return TCL_ERROR;
    }







|







1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Object *oPtr;
    Class *clsPtr;
    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;
    }
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
    Method *mPtr;
    Class *clsPtr;
    static const char *const options[] = {
	"-all", "-localprivate", "-private", "-scope", NULL
    };
    enum Options {
	OPT_ALL, OPT_LOCALPRIVATE, OPT_PRIVATE, OPT_SCOPE
    };
    static const char *const scopes[] = {
	"private", "public", "unexported"
    };
    enum Scopes {
	SCOPE_PRIVATE, SCOPE_PUBLIC, SCOPE_UNEXPORTED
    };

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?-option value ...?");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    if (objc != 2) {
	int i, idx;

	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) {
	    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);
		    return TCL_ERROR;
		}
		if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0,
			&scope) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;







|
















|






|














|







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
    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
    };

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?-option value ...?");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    if (objc != 2) {
	int i;

	for (i=2 ; i<objc ; i++) {
	    if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0,
		    &idx) != TCL_OK) {
		return TCL_ERROR;
	    }
	    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",
			    (char *)NULL);
		    return TCL_ERROR;
		}
		if (Tcl_GetIndexFromObj(interp, objv[i], scopes, "scope", 0,
			&scope) != TCL_OK) {
		    return TCL_ERROR;
		}
		break;
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
	    break;
	}
    }

    TclNewObj(resultObj);
    if (recurse) {
	const char **names;
	int i, numNames = TclOOGetSortedClassMethodList(clsPtr, flag, &names);

	for (i=0 ; i<numNames ; i++) {
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(names[i], -1));
	}
	if (numNames > 0) {
	    Tcl_Free((void *)names);







|







1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
	    break;
	}
    }

    TclNewObj(resultObj);
    if (recurse) {
	const char **names;
	Tcl_Size i, numNames = TclOOGetSortedClassMethodList(clsPtr, flag, &names);

	for (i=0 ; i<numNames ; i++) {
	    Tcl_ListObjAppendElement(NULL, resultObj,
		    Tcl_NewStringObj(names[i], -1));
	}
	if (numNames > 0) {
	    Tcl_Free((void *)names);
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }

    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, (char *) objv[2]);
    if (hPtr == NULL) {
    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);
    if (mPtr->typePtr == NULL) {
	/*
	 * Special entry for visibility control: pretend the method doesnt
	 * exist.







|





|







1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }

    hPtr = Tcl_FindHashEntry(&clsPtr->classMethods, objv[2]);
    if (hPtr == NULL) {
    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;
    }
    mPtr = (Method *)Tcl_GetHashValue(hPtr);
    if (mPtr->typePtr == NULL) {
	/*
	 * Special entry for visibility control: pretend the method doesnt
	 * exist.
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr, *mixinPtr;
    Tcl_Obj *resultObj;
    int i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {







|







1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr, *mixinPtr;
    Tcl_Obj *resultObj;
    Tcl_Size i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr, *subclassPtr;
    Tcl_Obj *resultObj;
    int 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]);







|







1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr, *subclassPtr;
    Tcl_Obj *resultObj;
    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]);
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr, *superPtr;
    Tcl_Obj *resultObj;
    int i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {







|







1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr, *superPtr;
    Tcl_Obj *resultObj;
    Tcl_Size i;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
1584
1585
1586
1587
1588
1589
1590

1591
1592
1593
1594
1595
1596
1597
1598
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr;
    Tcl_Obj *resultObj;

    int i, 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) {







>
|







1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Class *clsPtr;
    Tcl_Obj *resultObj;
    Tcl_Size i;
    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) {
1708
1709
1710
1711
1712
1713
1714


















































































































































































1715
1716
1717
1718
1719
1720
1721
1722
		"cannot construct any call chain", -1));
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, TclOORenderCallChain(interp, callPtr));
    TclOODeleteChain(callPtr);
    return TCL_OK;
}



















































































































































































/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








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
		"cannot construct any call chain", -1));
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, TclOORenderCallChain(interp, callPtr));
    TclOODeleteChain(callPtr);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * InfoClassPropCmd, InfoObjectPropCmd --
 *
 *	Implements [info class properties $clsName ?$option...?] and
 *	[info object properties $objName ?$option...?]
 *
 * ----------------------------------------------------------------------
 */

enum PropOpt {
    PROP_ALL, PROP_READABLE, PROP_WRITABLE
};
static const char *const propOptNames[] = {
    "-all", "-readable", "-writable",
    NULL
};

static int
InfoClassPropCmd(
    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, *propObj;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "className ?options...?");
	return TCL_ERROR;
    }
    clsPtr = GetClassFromObj(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 = TclOOGetAllClassProperties(clsPtr, writable, &allocated);
	if (allocated) {
	    SortPropList(result);
	}
    } else {
	TclNewObj(result);
	if (writable) {
	    FOREACH(propObj, clsPtr->properties.writable) {
		Tcl_ListObjAppendElement(NULL, result, propObj);
	    }
	} else {
	    FOREACH(propObj, clsPtr->properties.readable) {
		Tcl_ListObjAppendElement(NULL, result, propObj);
	    }
	}
	SortPropList(result);
    }
    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

static int
InfoObjectPropCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Object *oPtr;
    int i, idx, all = 0, writable = 0, allocated = 0;
    Tcl_Obj *result, *propObj;

    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, &allocated);
	if (allocated) {
	    SortPropList(result);
	}
    } else {
	TclNewObj(result);
	if (writable) {
	    FOREACH(propObj, oPtr->properties.writable) {
		Tcl_ListObjAppendElement(NULL, result, propObj);
	    }
	} else {
	    FOREACH(propObj, oPtr->properties.readable) {
		Tcl_ListObjAppendElement(NULL, result, propObj);
	    }
	}
	SortPropList(result);
    }
    Tcl_SetObjResult(interp, result);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * 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 strcmp(Tcl_GetString(first), Tcl_GetString(second));
}

static void
SortPropList(
    Tcl_Obj *list)
{
    Tcl_Size ec;
    Tcl_Obj **ev;

    Tcl_ListObjGetElements(NULL, list, &ec, &ev);
    qsort(ev, ec, sizeof(Tcl_Obj *), PropNameCompare);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */

Changes to generic/tclOOInt.h.

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 */

typedef struct Method {
    const Tcl_MethodType *typePtr;
				/* 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. */
    Tcl_Obj *namePtr;		/* Name of the method. */
    struct 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







|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 */

typedef struct Method {
    const Tcl_MethodType *typePtr;
				/* The type of method. If NULL, this is a
				 * special flag record which is just used for
				 * the setting of the flags 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
				 * NULL if it was declared by a class. */
    struct Class *declaringClassPtr;
				/* The class that declares this method, or
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
typedef struct ProcedureMethod {
    int version;		/* Version of this structure. Currently must
				 * be 0. */
    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;
    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. */







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
typedef struct ProcedureMethod {
    int version;		/* Version of this structure. Currently must
				 * be 0. */
    Proc *procPtr;		/* Core of the implementation of the method;
				 * includes the argument definition and the
				 * body bytecodes. */
    int flags;			/* Flags to control features. */
    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. */
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162




















163
164
165
166
167
168
169
 *
 * 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; }
#define LIST_DYNAMIC(listType_t) \
    struct { int num, size; listType_t *list; }

/*
 * These types are needed in function arguments.
 */

typedef LIST_STATIC(Tcl_Obj *) VariableNameList;
typedef LIST_STATIC(PrivateVariableMapping) PrivateVariableList;





















/*
 * Now, the definition of what an object actually is.
 */

typedef struct Object {
    struct Foundation *fPtr;	/* The basis for the object system. Putting
				 * this here allows the avoidance of quite a







|

|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
 *
 * 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 { Tcl_Size num; listType_t *list; }
#define LIST_DYNAMIC(listType_t) \
    struct { Tcl_Size num, size; listType_t *list; }

/*
 * These types are needed in function arguments.
 */

typedef LIST_STATIC(Tcl_Obj *) VariableNameList;
typedef LIST_STATIC(PrivateVariableMapping) PrivateVariableList;

/*
 * This type is used in various places.
 */

typedef struct {
    LIST_STATIC(Tcl_Obj *) readable;
				/* The readable properties slot. */
    LIST_STATIC(Tcl_Obj *) 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. */
} PropertyStorage;

/*
 * Now, the definition of what an object actually is.
 */

typedef struct Object {
    struct Foundation *fPtr;	/* The basis for the object system. Putting
				 * this here allows the avoidance of quite a
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237




238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
    Tcl_HashTable *methodsPtr;	/* Object-local Tcl_Obj (method name) to
				 * Method* mapping. */
    LIST_STATIC(struct Class *) 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.
				 * 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
				 * easier. */
    size_t 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. */



} Object;

#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 */
#define OO_UNUSED_4	4	/* No longer used.  */
#define 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; 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
				 * 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
				 * 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
				 * unknown method handler at that point. */




#define HAS_PRIVATE_METHODS 0x20000
				/* 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 {







|
|
|




|

|



















>
>
>


|
|
|
|


















>
>
>
>
|



<
<
<
<







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268




269
270
271
272
273
274
275
    Tcl_HashTable *methodsPtr;	/* Object-local Tcl_Obj (method name) to
				 * Method* mapping. */
    LIST_STATIC(struct Class *) 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. */
    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;
    Tcl_Size creationEpoch;		/* Unique value to make comparisons of objects
				 * easier. */
    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
				 * properties that this object *claims* to
				 * support. */
} Object;

#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 */
#define OO_UNUSED_4	4	/* No longer used.  */
#define 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; 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
				 * 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
				 * 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
				 * unknown method handler at that point. */
#define 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 0x40000
				/* Object/class has (or had) private methods,
				 * and so shouldn't be cached so
				 * aggressively. */





/*
 * And the definition of a class. Note that every class also has an associated
 * object, through which it is manipulated.
 */

typedef struct Class {
315
316
317
318
319
320
321



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
				 * 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. */



} 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.
 */

typedef struct ThreadLocalData {
    size_t 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;








>
>
>










|







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
				 * 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.
 */

typedef struct ThreadLocalData {
    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;

349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
    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
				 * 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







|







375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
    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. */
    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
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
				 * 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. */
};

typedef struct CallChain {
    size_t 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
				 * snapshot. */
    size_t 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
				 * staticChain if the number of entries is
				 * small. */
    struct MInvoke staticChain[CALL_CHAIN_STATIC_SIZE];
} CallChain;

typedef struct CallContext {
    Object *oPtr;		/* The object associated with this call. */
    int index;			/* Index into the call chain of the currently
				 * executing method implementation. */
    int 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;

/*







|


|

|


|
|








|

|







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
				 * 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. */
};

typedef 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. */
    Tcl_Size objectEpoch;	/* Local (object structure) epoch counter
				 * snapshot. */
    Tcl_Size epoch;		/* Global (class structure) epoch counter
				 * snapshot. */
    int flags;			/* Assorted flags, see below. */
    Tcl_Size refCount;		/* Reference count. */
    Tcl_Size numChain;		/* Size of the call chain. */
    struct 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;

typedef struct CallContext {
    Object *oPtr;		/* The object associated with this call. */
    Tcl_Size index;		/* Index into the call chain of the currently
				 * executing method implementation. */
    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;

/*
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
/*
 *----------------------------------------------------------------
 * Commands relating to OO support.
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclOOInit(Tcl_Interp *interp);
MODULE_SCOPE int	TclOODefineObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOOObjDefObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineConstructorObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineDeleteMethodObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineDestructorObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineExportObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineForwardObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineMethodObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOODefineRenameMethodObjCmd(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,
			    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,
			    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	TclOODefinePrivateObjCmd(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	TclOODefineDefnNsObjCmd(ClientData 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	TclOOSelfObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);

/*
 * Method implementations (in tclOOBasic.c).
 */

MODULE_SCOPE int	TclOO_Class_Constructor(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Class_Create(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Class_CreateNs(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Class_New(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_Destroy(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_Eval(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_LinkVar(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_Unknown(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
MODULE_SCOPE int	TclOO_Object_VarName(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);

/*
 * 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	TclNRNewObjectInstance(Tcl_Interp *interp,
			    Tcl_Class cls, const char *nameStr,
			    const char *nsNameStr, int objc,
			    Tcl_Obj *const *objv, int 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 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,
			    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 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,
			    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);







|
<
<
|
<
<
|
<
|
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
|
|
<
<
|
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<





|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<











>
>
>
>
>
>
>
>
>
>
>


|
|














>
>
>
>












|










|
|







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
/*
 *----------------------------------------------------------------
 * Commands relating to OO support.
 *----------------------------------------------------------------
 */

MODULE_SCOPE int	TclOOInit(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOOObjDefObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineConstructorObjCmd;

MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDefnNsObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDeleteMethodObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDestructorObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineExportObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineForwardObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineMethodObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineRenameMethodObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineUnexportObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineClassObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineSelfObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineObjSelfObjCmd;

MODULE_SCOPE Tcl_ObjCmdProc	TclOODefinePrivateObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOUnknownDefinition;


MODULE_SCOPE Tcl_ObjCmdProc	TclOOCopyObjectCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOONextObjCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOONextToObjCmd;
































MODULE_SCOPE Tcl_ObjCmdProc	TclOOSelfObjCmd;



/*
 * Method implementations (in tclOOBasic.c).
 */

MODULE_SCOPE Tcl_MethodCallProc	TclOO_Class_Constructor;


MODULE_SCOPE Tcl_MethodCallProc	TclOO_Class_Create;


MODULE_SCOPE Tcl_MethodCallProc	TclOO_Class_CreateNs;


MODULE_SCOPE Tcl_MethodCallProc	TclOO_Class_New;


MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_Destroy;


MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_Eval;


MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_LinkVar;


MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_Unknown;


MODULE_SCOPE Tcl_MethodCallProc	TclOO_Object_VarName;



/*
 * 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_Interp *interp, 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, 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 Tcl_Obj *	TclOOGetAllClassProperties(Class *clsPtr,
			    int writable, int *allocated);
MODULE_SCOPE Tcl_Obj *	TclOOGetAllObjectProperties(Object *oPtr,
			    int writable, int *allocated);
MODULE_SCOPE CallContext *TclOOGetCallContext(Object *oPtr,
			    Tcl_Obj *methodNameObj, int flags,
			    Object *contextObjPtr, Class *contextClsPtr,
			    Tcl_Obj *cacheInThisObj);
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 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 int	TclNRObjectContextInvokeNext(Tcl_Interp *interp,
			    Tcl_ObjectContext context, Tcl_Size objc,
			    Tcl_Obj *const *objv, Tcl_Size skip);
MODULE_SCOPE void	TclOONewBasicMethod(Tcl_Interp *interp, 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);
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
 */

#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;
 */

#define FOREACH(var,ary) \
    for(i=0 ; i<(ary).num; i++) if ((ary).list[i] == NULL) { \
	continue; \
    } 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;
 */

#define FOREACH_STRUCT(var,ary) \
    for(i=0 ; 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.
 * REQUIRES DECLARATION: FOREACH_HASH_DECLS;







|





|




|
|



|







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
 */

#define AddRef(ptr) ((ptr)->refCount++)

/*
 * A convenience macro for iterating through the lists used in the internal
 * memory management of objects.
 * 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)

/*
 * 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
 * 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) \
    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.
 * REQUIRES DECLARATION: FOREACH_HASH_DECLS;

Changes to generic/tclOOIntDecls.h.

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,
				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);







|







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,
				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
				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,
				Tcl_Obj *const *objv);
/* 12 */
TCLAPI void		TclOOObjectSetFilters(Object *oPtr, int numFilters,
				Tcl_Obj *const *filters);
/* 13 */
TCLAPI void		TclOOClassSetFilters(Tcl_Interp *interp,
				Class *classPtr, int numFilters,
				Tcl_Obj *const *filters);
/* 14 */
TCLAPI void		TclOOObjectSetMixins(Object *oPtr, int numMixins,
				Class *const *mixins);
/* 15 */
TCLAPI void		TclOOClassSetMixins(Tcl_Interp *interp,
				Class *classPtr, int 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 (*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 */
} TclOOIntStubs;

extern const TclOOIntStubs *tclOOIntStubsPtr;

#ifdef __cplusplus
}
#endif







|


|
|


|


|
|


|











|





|
|
|
|
|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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, Tcl_Size objc,
				Tcl_Obj *const *objv);
/* 12 */
TCLAPI void		TclOOObjectSetFilters(Object *oPtr,
				Tcl_Size numFilters, Tcl_Obj *const *filters);
/* 13 */
TCLAPI void		TclOOClassSetFilters(Tcl_Interp *interp,
				Class *classPtr, Tcl_Size numFilters,
				Tcl_Obj *const *filters);
/* 14 */
TCLAPI void		TclOOObjectSetMixins(Object *oPtr,
				Tcl_Size numMixins, Class *const *mixins);
/* 15 */
TCLAPI void		TclOOClassSetMixins(Tcl_Interp *interp,
				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, 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, 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
/*
 * tclOOMethod.c --
 *
 *	This file contains code to create and manage methods.
 *
 * Copyright (c) 2005-2011 by 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. */
};





|














|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
 * tclOOMethod.c --
 *
 *	This file contains code to create and manage methods.
 *
 * 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 invocation 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. */
};
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
 *
 *	Attach a method to an object instance.
 *
 * ----------------------------------------------------------------------
 */

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. */







|







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
 *
 *	Attach a method to an object instance.
 *
 * ----------------------------------------------------------------------
 */

Tcl_Method
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. */
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
	goto populate;
    }
    if (!oPtr->methodsPtr) {
	oPtr->methodsPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
	Tcl_InitObjHashTable(oPtr->methodsPtr);
	oPtr->flags &= ~USE_CLASS_CACHE;
    }
    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) nameObj, &isNew);
    if (isNew) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr->namePtr = nameObj;
	mPtr->refCount = 1;
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(hPtr, mPtr);
    } else {







|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
	goto populate;
    }
    if (!oPtr->methodsPtr) {
	oPtr->methodsPtr = (Tcl_HashTable *)Tcl_Alloc(sizeof(Tcl_HashTable));
	Tcl_InitObjHashTable(oPtr->methodsPtr);
	oPtr->flags &= ~USE_CLASS_CACHE;
    }
    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, nameObj, &isNew);
    if (isNew) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr->namePtr = nameObj;
	mPtr->refCount = 1;
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(hPtr, mPtr);
    } else {
183
184
185
186
187
188
189












































190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
	if (flags & TRUE_PRIVATE_METHOD) {
	    oPtr->flags |= HAS_PRIVATE_METHODS;
	}
    }
    oPtr->epoch++;
    return (Tcl_Method) mPtr;
}













































/*
 * ----------------------------------------------------------------------
 *
 * Tcl_NewMethod --
 *
 *	Attach a method to a class.
 *
 * ----------------------------------------------------------------------
 */

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,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
	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 TCL_OO_METHOD_VERSION_1", "Tcl_NewInstanceMethod");
    }
    return TclNewInstanceMethod(NULL, object, nameObj, flags,
	    (const Tcl_MethodType *)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 TCL_OO_METHOD_VERSION_2", "Tcl_NewInstanceMethod2");
    }
    return TclNewInstanceMethod(NULL, object, nameObj, flags,
	    (const Tcl_MethodType *)typePtr, clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * Tcl_NewMethod --
 *
 *	Attach a method to a class.
 *
 * ----------------------------------------------------------------------
 */

Tcl_Method
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,
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

    if (nameObj == NULL) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr->namePtr = NULL;
	mPtr->refCount = 1;
	goto populate;
    }
    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)nameObj,&isNew);
    if (isNew) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr->refCount = 1;
	mPtr->namePtr = nameObj;
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(hPtr, mPtr);
    } else {







|







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278

    if (nameObj == NULL) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr->namePtr = NULL;
	mPtr->refCount = 1;
	goto populate;
    }
    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, nameObj,&isNew);
    if (isNew) {
	mPtr = (Method *)Tcl_Alloc(sizeof(Method));
	mPtr->refCount = 1;
	mPtr->namePtr = nameObj;
	Tcl_IncrRefCount(nameObj);
	Tcl_SetHashValue(hPtr, mPtr);
    } else {
251
252
253
254
255
256
257










































258
259
260
261
262
263
264
	if (flags & TRUE_PRIVATE_METHOD) {
	    clsPtr->flags |= HAS_PRIVATE_METHODS;
	}
    }

    return (Tcl_Method) mPtr;
}











































/*
 * ----------------------------------------------------------------------
 *
 * TclOODelMethodRef --
 *
 *	How to delete a method.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	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 TCL_OO_METHOD_VERSION_1", "Tcl_NewMethod");
    }
    return TclNewMethod(NULL, 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 TCL_OO_METHOD_VERSION_2", "Tcl_NewMethod2");
    }
    return TclNewMethod(NULL, cls, nameObj, flags, (const Tcl_MethodType *)typePtr, clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODelMethodRef --
 *
 *	How to delete a method.
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    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);

    Tcl_IncrRefCount(namePtr);
    Tcl_NewMethod(interp, (Tcl_Class) clsPtr, namePtr,
	    (dcm->isPublic ? PUBLIC_METHOD : 0), &dcm->definition, NULL);
    Tcl_DecrRefCount(namePtr);
}

/*
 * ----------------------------------------------------------------------
 *







|







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
    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);

    Tcl_IncrRefCount(namePtr);
    TclNewMethod(interp, (Tcl_Class) clsPtr, namePtr,
	    (dcm->isPublic ? PUBLIC_METHOD : 0), &dcm->definition, NULL);
    Tcl_DecrRefCount(namePtr);
}

/*
 * ----------------------------------------------------------------------
 *
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
    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;
    ProcedureMethod *pmPtr;
    Tcl_Method method;

    if (Tcl_ListObjLength(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;







|



|







417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
    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. */
{
    Tcl_Size argsLen;
    ProcedureMethod *pmPtr;
    Tcl_Method method;

    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;
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
    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 */
    ProcedureMethod *pmPtr;
    const char *procName;
    Tcl_Method method;

    if (argsObj == NULL) {
	argsLen = -1;
	TclNewObj(argsObj);
	Tcl_IncrRefCount(argsObj);
	procName = "<destructor>";
    } else if (Tcl_ListObjLength(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;

    method = TclOOMakeProcMethod(interp, clsPtr, flags, nameObj, procName,
	    argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr);

    if (argsLen == -1) {
	Tcl_DecrRefCount(argsObj);
    }
    if (method == NULL) {
	Tcl_Free(pmPtr);
    } else if (pmPtrPtr != NULL) {
	*pmPtrPtr = pmPtr;
    }







|





|



|














|







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
    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. */
{
    Tcl_Size argsLen;		/* TCL_INDEX_NONE => delete argsObj before exit */
    ProcedureMethod *pmPtr;
    const char *procName;
    Tcl_Method method;

    if (argsObj == NULL) {
	argsLen = TCL_INDEX_NONE;
	TclNewObj(argsObj);
	Tcl_IncrRefCount(argsObj);
	procName = "<destructor>";
    } 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;

    method = TclOOMakeProcMethod(interp, clsPtr, flags, nameObj, procName,
	    argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr);

    if (argsLen == TCL_INDEX_NONE) {
	Tcl_DecrRefCount(argsObj);
    }
    if (method == NULL) {
	Tcl_Free(pmPtr);
    } else if (pmPtrPtr != NULL) {
	*pmPtrPtr = pmPtr;
    }
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
		    && (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,
	    typePtr, clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOMakeProcMethod --







|












|













|







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
		    && (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 = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size));
		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,
			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 TclNewInstanceMethod(interp, (Tcl_Object) oPtr, nameObj, flags,
	    typePtr, clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOMakeProcMethod --
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
		    && (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,
	    clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * InvokeProcedureMethod, PushMethodCallFrame --







|












|













|







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
		    && (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 = (Tcl_Size *)Tcl_Alloc(sizeof(Tcl_Size));
		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,
			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 TclNewMethod(interp, (Tcl_Class) clsPtr, nameObj, flags, typePtr,
	    clientData);
}

/*
 * ----------------------------------------------------------------------
 *
 * InvokeProcedureMethod, PushMethodCallFrame --
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
				 * 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)
    ) {
	return TclNRObjectContextInvokeNext(interp, context, objc, objv,
		Tcl_ObjectContextSkippedArgs(context));
    }

    /*
     * Allocate the special frame data.
     */







|
|
<







757
758
759
760
761
762
763
764
765

766
767
768
769
770
771
772
				 * 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)) {

	return TclNRObjectContextInvokeNext(interp, context, objc, objv,
		Tcl_ObjectContextSkippedArgs(context));
    }

    /*
     * Allocate the special frame data.
     */
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
    /*
     * [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...
     */

    ByteCodeGetIntRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, codePtr);
    if (codePtr) {
	codePtr->nsPtr = nsPtr;
    }
    result = TclProcCompileProc(interp, pmPtr->procPtr,
	    pmPtr->procPtr->bodyPtr, nsPtr, "body of method", namePtr);
    if (result != TCL_OK) {
	goto failureReturn;







|







940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
    /*
     * [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...
     */

    ByteCodeGetInternalRep(pmPtr->procPtr->bodyPtr, &tclByteCodeType, codePtr);
    if (codePtr) {
	codePtr->nsPtr = nsPtr;
    }
    result = TclProcCompileProc(interp, pmPtr->procPtr,
	    pmPtr->procPtr->bodyPtr, nsPtr, "body of method", namePtr);
    if (result != TCL_OK) {
	goto failureReturn;
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
    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;
    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.
     */







|
|







1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
    OOResVarInfo *infoPtr = (OOResVarInfo *) rPtr;
    Interp *iPtr = (Interp *) interp;
    CallFrame *framePtr = iPtr->varFramePtr;
    CallContext *contextPtr;
    Tcl_Obj *variableObj;
    PrivateVariableMapping *privateVar;
    Tcl_HashEntry *hPtr;
    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.
     */
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

    /*
     * 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);
    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);
	    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);
	    if ((len == varLen) && !memcmp(match, varName, len)) {
		cacheIt = 0;
		goto gotMatch;
	    }
	}
    } else {
	FOREACH_STRUCT(privateVar, contextPtr->oPtr->privateVariables) {
	    match = TclGetStringFromObj(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);
	    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);
    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

    /*
     * 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 = 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 = 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 = Tcl_GetStringFromObj(variableObj, &len);
	    if ((len == varLen) && !memcmp(match, varName, len)) {
		cacheIt = 0;
		goto gotMatch;
	    }
	}
    } else {
	FOREACH_STRUCT(privateVar, contextPtr->oPtr->privateVariables) {
	    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 = 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),
	    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
    Tcl_Free(infoPtr);
}

static int
ProcedureMethodCompiledVarResolver(
    TCL_UNUSED(Tcl_Interp *),
    const char *varName,
    int length,
    TCL_UNUSED(Tcl_Namespace *),
    Tcl_ResolvedVarInfo **rPtrPtr)
{
    OOResVarInfo *infoPtr;
    Tcl_Obj *variableObj = Tcl_NewStringObj(varName, length);

    /*







|







1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
    Tcl_Free(infoPtr);
}

static int
ProcedureMethodCompiledVarResolver(
    TCL_UNUSED(Tcl_Interp *),
    const char *varName,
    Tcl_Size length,
    TCL_UNUSED(Tcl_Namespace *),
    Tcl_ResolvedVarInfo **rPtrPtr)
{
    OOResVarInfo *infoPtr;
    Tcl_Obj *variableObj = Tcl_NewStringObj(varName, length);

    /*
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

static void
MethodErrorHandler(
    Tcl_Interp *interp,
    TCL_UNUSED(Tcl_Obj *) /*methodNameObj*/)
	/* We pull the method name out of context instead of from argument */
{
    size_t 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);
    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 = TclGetStringFromObj(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;
    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\" 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)));
}

/*







|



|













|

















|












|
















|












|







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

static void
MethodErrorHandler(
    Tcl_Interp *interp,
    TCL_UNUSED(Tcl_Obj *) /*methodNameObj*/)
	/* We pull the method name out of context instead of from argument */
{
    Tcl_Size nameLen, objectNameLen;
    CallContext *contextPtr = (CallContext *)((Interp *) interp)->varFramePtr->clientData;
    Method *mPtr = contextPtr->callPtr->chain[contextPtr->index].mPtr;
    const char *objectName, *kindName, *methodName =
	    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 = 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;
    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 = Tcl_GetStringFromObj(TclOOObjectName(interp, declarerPtr),
	    &objectNameLen);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (%s \"%.*s%s\" destructor line %d)", kindName,
	    ELLIPSIFY(objectName, objectNameLen), Tcl_GetErrorLine(interp)));
}

/*
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
    /*
     * 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);

    /*
     * Create the actual copy of the method record, manufacturing a new proc
     * record.
     */

    pm2Ptr = (ProcedureMethod *)Tcl_Alloc(sizeof(ProcedureMethod));







|







1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
    /*
     * 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_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));
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
    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;
    ForwardMethod *fmPtr;

    if (Tcl_ListObjLength(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);
	return NULL;
    }

    fmPtr = (ForwardMethod *)Tcl_Alloc(sizeof(ForwardMethod));
    fmPtr->prefixObj = prefixObj;
    Tcl_IncrRefCount(prefixObj);
    return (Method *) Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr,
	    nameObj, flags, &fwdMethodType, fmPtr);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOONewForwardMethod --







|


|





|






|







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
    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. */
{
    Tcl_Size prefixLen;
    ForwardMethod *fmPtr;

    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", (char *)NULL);
	return NULL;
    }

    fmPtr = (ForwardMethod *)Tcl_Alloc(sizeof(ForwardMethod));
    fmPtr->prefixObj = prefixObj;
    Tcl_IncrRefCount(prefixObj);
    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
    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;
    ForwardMethod *fmPtr;

    if (Tcl_ListObjLength(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);
	return NULL;
    }

    fmPtr = (ForwardMethod *)Tcl_Alloc(sizeof(ForwardMethod));
    fmPtr->prefixObj = prefixObj;
    Tcl_IncrRefCount(prefixObj);
    return (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, nameObj,
	    flags, &fwdMethodType, fmPtr);
}

/*
 * ----------------------------------------------------------------------
 *
 * InvokeForwardMethod --







|


|





|






|







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
    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. */
{
    Tcl_Size prefixLen;
    ForwardMethod *fmPtr;

    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", (char *)NULL);
	return NULL;
    }

    fmPtr = (ForwardMethod *)Tcl_Alloc(sizeof(ForwardMethod));
    fmPtr->prefixObj = prefixObj;
    Tcl_IncrRefCount(prefixObj);
    return (Method *) TclNewMethod(interp, (Tcl_Class) clsPtr, nameObj,
	    flags, &fwdMethodType, fmPtr);
}

/*
 * ----------------------------------------------------------------------
 *
 * InvokeForwardMethod --
1464
1465
1466
1467
1468
1469
1470
1471

1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
    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;
    Tcl_Obj **argObjs, **prefixObjs;
    int numPrefixes, len, skip = contextPtr->skip;


    /*
     * 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);
    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.







|
>








|







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
    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;
    Tcl_Obj **argObjs, **prefixObjs;
    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.
     */

    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.
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
    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);

    memcpy(argObjs, rewriteObjs, rewriteLength * sizeof(Tcl_Obj *));
    memcpy(argObjs + rewriteLength, objv + toRewrite,
	    sizeof(Tcl_Obj *) * (objc - toRewrite));

    /*







|







1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
    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. */
{
    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));

    /*
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

Tcl_Obj *
Tcl_MethodName(
    Tcl_Method method)
{
    return ((Method *) method)->namePtr;
}


















int
Tcl_MethodIsType(
    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_MethodIsPublic(







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

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 TCL_OO_METHOD_VERSION_1", "Tcl_MethodIsType");
    }
    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 TCL_OO_METHOD_VERSION_2", "Tcl_MethodIsType2");
    }
    if (mPtr->typePtr == (const Tcl_MethodType *)typePtr) {
	if (clientDataPtr != NULL) {
	    *clientDataPtr = mPtr->clientData;
	}
	return 1;
    }
    return 0;
}

int
Tcl_MethodIsPublic(

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

#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
 * 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\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"







|









|







15
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 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\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
"\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\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"







|







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 {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
"\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}\n"
"\t\tobjdefine $class ::oo::objdefine::mixin -append $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"
"\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}\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\t}\n"
"\t\tmethod Set list {\n"
"\t\t\treturn -code error -errorcode {TCLOO ABSTRACT_SLOT} \"unimplemented\"\n"
"\t\t}\n"
"\t\tmethod Resolve list {\n"
"\t\t\treturn $list\n"
"\t\t}\n"
"\t\tmethod -set 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\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 -clear {} {tailcall my Set {}}\n"
"\t\tmethod -prepend 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\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\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}\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"
"\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"







|

|















|








|















|
|

|
|

|


|




|





>
>
>
>
>
>
>
>
>
>
>
|
|





|








|








<
|




|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
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 -appendifnew $d\n"
"\t\t}\n"
"\t\tobjdefine $class ::oo::objdefine::mixin -appendifnew $delegate\n"
"\t}\n"
"\tproc UpdateClassDelegatesAfterClone {originObject targetObject} {\n"
"\t\tset originDelegate [DelegateName $originObject]\n"
"\t\tset targetDelegate [DelegateName $targetObject]\n"
"\t\tif {\n"
"\t\t\t[info object isa class $originDelegate]\n"
"\t\t\t&& ![info object isa class $targetDelegate]\n"
"\t\t} then {\n"
"\t\t\tcopy $originDelegate $targetDelegate\n"
"\t\t\tobjdefine $targetObject ::oo::objdefine::mixin -set \\\n"
"\t\t\t\t{*}[lmap c [info object mixin $targetObject] {\n"
"\t\t\t\t\tif {$c eq $originDelegate} {set targetDelegate} {set c}\n"
"\t\t\t\t}]\n"
"\t\t}\n"
"\t}\n"
"\tproc define::classmethod {name args} {\n"
"\t\t::set argc [::llength [::info level 0]]\n"
"\t\t::if {$argc == 3} {\n"
"\t\t\t::return -code error -errorcode {TCL WRONGARGS} [::format \\\n"
"\t\t\t\t{wrong # args: should be \"%s name \?args body\?\"} \\\n"
"\t\t\t\t[::lindex [::info level 0] 0]]\n"
"\t\t}\n"
"\t\t::set cls [::uplevel 1 self]\n"
"\t\t::if {$argc == 4} {\n"
"\t\t\t::oo::define [::oo::DelegateName $cls] method $name {*}$args\n"
"\t\t}\n"
"\t\t::tailcall forward $name myclass $name\n"
"\t}\n"
"\tproc define::initialise {body} {\n"
"\t\t::set clsns [::info object namespace [::uplevel 1 self]]\n"
"\t\t::tailcall apply [::list {} $body $clsns]\n"
"\t}\n"
"\tnamespace eval define {\n"
"\t\t::namespace export initialise\n"
"\t\t::namespace eval tmp {::namespace import ::oo::define::initialise}\n"
"\t\t::namespace export -clear\n"
"\t\t::rename tmp::initialise initialize\n"
"\t\t::namespace delete tmp\n"
"\t}\n"
"\tdefine Slot {\n"
"\t\tmethod Get -unexport {} {\n"
"\t\t\treturn -code error -errorcode {TCL OO ABSTRACT_SLOT} \"unimplemented\"\n"
"\t\t}\n"
"\t\tmethod Set -unexport list {\n"
"\t\t\treturn -code error -errorcode {TCL OO ABSTRACT_SLOT} \"unimplemented\"\n"
"\t\t}\n"
"\t\tmethod Resolve -unexport list {\n"
"\t\t\treturn $list\n"
"\t\t}\n"
"\t\tmethod -set -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\ttailcall my Set $args\n"
"\t\t}\n"
"\t\tmethod -append -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\ttailcall my Set [list {*}$current {*}$args]\n"
"\t\t}\n"
"\t\tmethod -appendifnew -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\tforeach a $args {\n"
"\t\t\t\tset a [uplevel 1 [list $my Resolve $a]]\n"
"\t\t\t\tif {$a ni $current} {\n"
"\t\t\t\t\tlappend current $a\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t\ttailcall my Set $current\n"
"\t\t}\n"
"\t\tmethod -clear -export {} {tailcall my Set {}}\n"
"\t\tmethod -prepend -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\ttailcall my Set [list {*}$args {*}$current]\n"
"\t\t}\n"
"\t\tmethod -remove -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\ttailcall my Set [lmap val $current {\n"
"\t\t\t\tif {$val in $args} continue else {set val}\n"
"\t\t\t}]\n"
"\t\t}\n"
"\t\tforward --default-operation my -append\n"
"\t\tmethod unknown -unexport {args} {\n"
"\t\t\tset def --default-operation\n"
"\t\t\tif {[llength $args] == 0} {\n"
"\t\t\t\ttailcall my $def\n"
"\t\t\t} elseif {![string match -* [lindex $args 0]]} {\n"
"\t\t\t\ttailcall my $def {*}$args\n"
"\t\t\t}\n"
"\t\t\tnext {*}$args\n"
"\t\t}\n"

"\t\tunexport destroy\n"
"\t}\n"
"\tobjdefine define::superclass forward --default-operation my -set\n"
"\tobjdefine define::mixin forward --default-operation my -set\n"
"\tobjdefine objdefine::mixin forward --default-operation my -set\n"
"\tdefine object method <cloned> -unexport {originObject} {\n"
"\t\tforeach p [info procs [info object namespace $originObject]::*] {\n"
"\t\t\tset args [info args $p]\n"
"\t\t\tset idx -1\n"
"\t\t\tforeach a $args {\n"
"\t\t\t\tif {[info default $p $a d]} {\n"
"\t\t\t\t\tlset args [incr idx] [list $a $d]\n"
"\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
"\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"
"\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\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\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"




























































































































































































































"}\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:
 */







|












|


|
|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
"\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> -unexport {originObject} {\n"
"\t\tnext $originObject\n"
"\t\t::oo::UpdateClassDelegatesAfterClone $originObject [self]\n"
"\t}\n"
"\tclass create singleton {\n"
"\t\tsuperclass class\n"
"\t\tvariable object\n"
"\t\tunexport create createWithNamespace\n"
"\t\tmethod new args {\n"
"\t\t\tif {![info exists object] || ![info object isa object $object]} {\n"
"\t\t\t\tset object [next {*}$args]\n"
"\t\t\t\t::oo::objdefine $object {\n"
"\t\t\t\t\tmethod destroy {} {\n"
"\t\t\t\t\t\t::return -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\t\t\t\t\"may not destroy a singleton object\"\n"
"\t\t\t\t\t}\n"
"\t\t\t\t\tmethod <cloned> -unexport {originObject} {\n"
"\t\t\t\t\t\t::return -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\t\t\t\t\"may not clone a singleton object\"\n"
"\t\t\t\t\t}\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t\treturn $object\n"
"\t\t}\n"
"\t}\n"
"\tclass create abstract {\n"
"\t\tsuperclass class\n"
"\t\tunexport create createWithNamespace new\n"
"\t}\n"
"\t::namespace eval configuresupport {\n"
"\t\tnamespace path ::tcl\n"
"\t\tproc PropertyImpl {readslot writeslot args} {\n"
"\t\t\tfor {set i 0} {$i < [llength $args]} {incr i} {\n"
"\t\t\t\tset prop [lindex $args $i]\n"
"\t\t\t\tif {[string match \"-*\" $prop]} {\n"
"\t\t\t\t\treturn -code error -level 2 \\\n"
"\t\t\t\t\t\t-errorcode {TCL OO PROPERTY_FORMAT} \\\n"
"\t\t\t\t\t\t\"bad property name \\\"$prop\\\": must not begin with -\"\n"
"\t\t\t\t}\n"
"\t\t\t\tif {$prop ne [list $prop]} {\n"
"\t\t\t\t\treturn -code error -level 2 \\\n"
"\t\t\t\t\t\t-errorcode {TCL OO PROPERTY_FORMAT} \\\n"
"\t\t\t\t\t\t\"bad property name \\\"$prop\\\": must be a simple word\"\n"
"\t\t\t\t}\n"
"\t\t\t\tif {[string first \"::\" $prop] != -1} {\n"
"\t\t\t\t\treturn -code error -level 2 \\\n"
"\t\t\t\t\t\t-errorcode {TCL OO PROPERTY_FORMAT} \\\n"
"\t\t\t\t\t\t\"bad property name \\\"$prop\\\": must not contain namespace separators\"\n"
"\t\t\t\t}\n"
"\t\t\t\tif {[string match {*[()]*} $prop]} {\n"
"\t\t\t\t\treturn -code error -level 2 \\\n"
"\t\t\t\t\t\t-errorcode {TCL OO PROPERTY_FORMAT} \\\n"
"\t\t\t\t\t\t\"bad property name \\\"$prop\\\": must not contain parentheses\"\n"
"\t\t\t\t}\n"
"\t\t\t\tset realprop [string cat \"-\" $prop]\n"
"\t\t\t\tset getter [format {::set [my varname %s]} $prop]\n"
"\t\t\t\tset setter [format {::set [my varname %s] $value} $prop]\n"
"\t\t\t\tset kind readwrite\n"
"\t\t\t\twhile {[set next [lindex $args [expr {$i + 1}]]\n"
"\t\t\t\t\t\tstring match \"-*\" $next]} {\n"
"\t\t\t\t\tset arg [lindex $args [incr i 2]]\n"
"\t\t\t\t\tswitch [prefix match -error [list -level 2 -errorcode \\\n"
"\t\t\t\t\t\t\t[list TCL LOOKUP INDEX option $next]] {-get -kind -set} $next] {\n"
"\t\t\t\t\t\t-get {\n"
"\t\t\t\t\t\t\tif {$i >= [llength $args]} {\n"
"\t\t\t\t\t\t\t\treturn -code error -level 2 \\\n"
"\t\t\t\t\t\t\t\t\t-errorcode {TCL WRONGARGS} \\\n"
"\t\t\t\t\t\t\t\t\t\"missing body to go with -get option\"\n"
"\t\t\t\t\t\t\t}\n"
"\t\t\t\t\t\t\tset getter $arg\n"
"\t\t\t\t\t\t}\n"
"\t\t\t\t\t\t-set {\n"
"\t\t\t\t\t\t\tif {$i >= [llength $args]} {\n"
"\t\t\t\t\t\t\t\treturn -code error -level 2 \\\n"
"\t\t\t\t\t\t\t\t\t-errorcode {TCL WRONGARGS} \\\n"
"\t\t\t\t\t\t\t\t\t\"missing body to go with -set option\"\n"
"\t\t\t\t\t\t\t}\n"
"\t\t\t\t\t\t\tset setter $arg\n"
"\t\t\t\t\t\t}\n"
"\t\t\t\t\t\t-kind {\n"
"\t\t\t\t\t\t\tif {$i >= [llength $args]} {\n"
"\t\t\t\t\t\t\t\treturn -code error -level 2\\\n"
"\t\t\t\t\t\t\t\t\t-errorcode {TCL WRONGARGS} \\\n"
"\t\t\t\t\t\t\t\t\t\"missing kind value to go with -kind option\"\n"
"\t\t\t\t\t\t\t}\n"
"\t\t\t\t\t\t\tset kind [prefix match -message \"kind\" -error [list \\\n"
"\t\t\t\t\t\t\t\t\t-level 2 \\\n"
"\t\t\t\t\t\t\t\t\t-errorcode [list TCL LOOKUP INDEX kind $arg]] {\n"
"\t\t\t\t\t\t\t\treadable readwrite writable\n"
"\t\t\t\t\t\t\t} $arg]\n"
"\t\t\t\t\t\t}\n"
"\t\t\t\t\t}\n"
"\t\t\t\t}\n"
"\t\t\t\tset reader <ReadProp$realprop>\n"
"\t\t\t\tset writer <WriteProp$realprop>\n"
"\t\t\t\tswitch $kind {\n"
"\t\t\t\t\treadable {\n"
"\t\t\t\t\t\tuplevel 2 [list $readslot -append $realprop]\n"
"\t\t\t\t\t\tuplevel 2 [list $writeslot -remove $realprop]\n"
"\t\t\t\t\t\tuplevel 2 [list method $reader -unexport {} $getter]\n"
"\t\t\t\t\t}\n"
"\t\t\t\t\twritable {\n"
"\t\t\t\t\t\tuplevel 2 [list $readslot -remove $realprop]\n"
"\t\t\t\t\t\tuplevel 2 [list $writeslot -append $realprop]\n"
"\t\t\t\t\t\tuplevel 2 [list method $writer -unexport {value} $setter]\n"
"\t\t\t\t\t}\n"
"\t\t\t\t\treadwrite {\n"
"\t\t\t\t\t\tuplevel 2 [list $readslot -append $realprop]\n"
"\t\t\t\t\t\tuplevel 2 [list $writeslot -append $realprop]\n"
"\t\t\t\t\t\tuplevel 2 [list method $reader -unexport {} $getter]\n"
"\t\t\t\t\t\tuplevel 2 [list method $writer -unexport {value} $setter]\n"
"\t\t\t\t\t}\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t}\n"
"\t\tnamespace eval configurableclass {\n"
"\t\t\t::proc property args {\n"
"\t\t\t\t::oo::configuresupport::PropertyImpl \\\n"
"\t\t\t\t\t::oo::configuresupport::readableproperties \\\n"
"\t\t\t\t\t::oo::configuresupport::writableproperties {*}$args\n"
"\t\t\t}\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\tnamespace eval configurableobject {\n"
"\t\t\t::proc property args {\n"
"\t\t\t\t::oo::configuresupport::PropertyImpl \\\n"
"\t\t\t\t\t::oo::configuresupport::objreadableproperties \\\n"
"\t\t\t\t\t::oo::configuresupport::objwritableproperties {*}$args\n"
"\t\t\t}\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\tproc ReadAll {object my} {\n"
"\t\t\tset result {}\n"
"\t\t\tforeach prop [info object properties $object -all -readable] {\n"
"\t\t\t\ttry {\n"
"\t\t\t\t\tdict set result $prop [$my <ReadProp$prop>]\n"
"\t\t\t\t} on error {msg opt} {\n"
"\t\t\t\t\tdict set opt -level 2\n"
"\t\t\t\t\treturn -options $opt $msg\n"
"\t\t\t\t} on return {msg opt} {\n"
"\t\t\t\t\tdict incr opt -level 2\n"
"\t\t\t\t\treturn -options $opt $msg\n"
"\t\t\t\t} on break {} {\n"
"\t\t\t\t\treturn -code error -level 2 -errorcode {TCL OO SHENANIGANS} \\\n"
"\t\t\t\t\t\t\"property getter for $prop did a break\"\n"
"\t\t\t\t} on continue {} {\n"
"\t\t\t\t\treturn -code error -level 2 -errorcode {TCL OO SHENANIGANS} \\\n"
"\t\t\t\t\t\t\"property getter for $prop did a continue\"\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t\treturn $result\n"
"\t\t}\n"
"\t\tproc ReadOne {object my propertyName} {\n"
"\t\t\tset props [info object properties $object -all -readable]\n"
"\t\t\ttry {\n"
"\t\t\t\tset prop [prefix match -message \"property\" $props $propertyName]\n"
"\t\t\t} on error {msg} {\n"
"\t\t\t\tcatch {\n"
"\t\t\t\t\tset wps [info object properties $object -all -writable]\n"
"\t\t\t\t\tset wprop [prefix match $wps $propertyName]\n"
"\t\t\t\t\tset msg \"property \\\"$wprop\\\" is write only\"\n"
"\t\t\t\t}\n"
"\t\t\t\treturn -code error -level 2 -errorcode [list \\\n"
"\t\t\t\t\t\tTCL LOOKUP INDEX property $propertyName] $msg\n"
"\t\t\t}\n"
"\t\t\ttry {\n"
"\t\t\t\tset value [$my <ReadProp$prop>]\n"
"\t\t\t} on error {msg opt} {\n"
"\t\t\t\tdict set opt -level 2\n"
"\t\t\t\treturn -options $opt $msg\n"
"\t\t\t} on return {msg opt} {\n"
"\t\t\t\tdict incr opt -level 2\n"
"\t\t\t\treturn -options $opt $msg\n"
"\t\t\t} on break {} {\n"
"\t\t\t\treturn -code error -level 2 -errorcode {TCL OO SHENANIGANS} \\\n"
"\t\t\t\t\t\"property getter for $prop did a break\"\n"
"\t\t\t} on continue {} {\n"
"\t\t\t\treturn -code error -level 2 -errorcode {TCL OO SHENANIGANS} \\\n"
"\t\t\t\t\t\"property getter for $prop did a continue\"\n"
"\t\t\t}\n"
"\t\t\treturn $value\n"
"\t\t}\n"
"\t\tproc WriteMany {object my setterMap} {\n"
"\t\t\tset props [info object properties $object -all -writable]\n"
"\t\t\tforeach {prop value} $setterMap {\n"
"\t\t\t\ttry {\n"
"\t\t\t\t\tset prop [prefix match -message \"property\" $props $prop]\n"
"\t\t\t\t} on error {msg} {\n"
"\t\t\t\t\tcatch {\n"
"\t\t\t\t\t\tset rps [info object properties $object -all -readable]\n"
"\t\t\t\t\t\tset rprop [prefix match $rps $prop]\n"
"\t\t\t\t\t\tset msg \"property \\\"$rprop\\\" is read only\"\n"
"\t\t\t\t\t}\n"
"\t\t\t\t\treturn -code error -level 2 -errorcode [list \\\n"
"\t\t\t\t\t\t\tTCL LOOKUP INDEX property $prop] $msg\n"
"\t\t\t\t}\n"
"\t\t\t\ttry {\n"
"\t\t\t\t\t$my <WriteProp$prop> $value\n"
"\t\t\t\t} on error {msg opt} {\n"
"\t\t\t\t\tdict set opt -level 2\n"
"\t\t\t\t\treturn -options $opt $msg\n"
"\t\t\t\t} on return {msg opt} {\n"
"\t\t\t\t\tdict incr opt -level 2\n"
"\t\t\t\t\treturn -options $opt $msg\n"
"\t\t\t\t} on break {} {\n"
"\t\t\t\t\treturn -code error -level 2 -errorcode {TCL OO SHENANIGANS} \\\n"
"\t\t\t\t\t\t\"property setter for $prop did a break\"\n"
"\t\t\t\t} on continue {} {\n"
"\t\t\t\t\treturn -code error -level 2 -errorcode {TCL OO SHENANIGANS} \\\n"
"\t\t\t\t\t\t\"property setter for $prop did a continue\"\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t\treturn\n"
"\t\t}\n"
"\t\t::oo::class create configurable {\n"
"\t\t\tprivate variable my\n"
"\t\t\tmethod configure -export args {\n"
"\t\t\t\t::if {![::info exists my]} {\n"
"\t\t\t\t\t::set my [::namespace which my]\n"
"\t\t\t\t}\n"
"\t\t\t\t::if {[::llength $args] == 0} {\n"
"\t\t\t\t\t::oo::configuresupport::ReadAll [self] $my\n"
"\t\t\t\t} elseif {[::llength $args] == 1} {\n"
"\t\t\t\t\t::oo::configuresupport::ReadOne [self] $my \\\n"
"\t\t\t\t\t\t[::lindex $args 0]\n"
"\t\t\t\t} elseif {[::llength $args] % 2 == 0} {\n"
"\t\t\t\t\t::oo::configuresupport::WriteMany [self] $my $args\n"
"\t\t\t\t} else {\n"
"\t\t\t\t\t::return -code error -errorcode {TCL WRONGARGS} \\\n"
"\t\t\t\t\t\t[::format {wrong # args: should be \"%s\"} \\\n"
"\t\t\t\t\t\t\t\"[self] configure \?-option value ...\?\"]\n"
"\t\t\t\t}\n"
"\t\t\t}\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
    Tcl_ObjectContextInvokeNext, /* 23 */
    Tcl_ObjectGetMethodNameMapper, /* 24 */
    Tcl_ObjectSetMethodNameMapper, /* 25 */
    Tcl_ClassSetConstructor, /* 26 */
    Tcl_ClassSetDestructor, /* 27 */
    Tcl_GetObjectName, /* 28 */
    Tcl_MethodIsPrivate, /* 29 */





};

/* !END!: Do not edit above this line. */







>
>
>
>
>



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

MODULE_SCOPE const char *
TclOOInitializeStubs(
    Tcl_Interp *interp,
    const char *version)
{
    int exact = 0;
    const char *packageName = "TclOO";
    const char *errMsg = NULL;
    TclOOStubs *stubsPtr = NULL;
    const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp,
	    packageName, version, exact, &stubsPtr);

    if (actualVersion == NULL) {




	return NULL;

    }
    if (stubsPtr == NULL) {
	errMsg = "missing stub table pointer";
    } else {
	tclOOStubsPtr = stubsPtr;
	if (stubsPtr->hooks) {
	    tclOOIntStubsPtr = stubsPtr->hooks->tclOOIntStubs;







|






>
>
>
>
|
>







31
32
33
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 = "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;
	}
    }
    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
/*
 * 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 <[email protected]>
 *
 * 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"






|
|
|
|
|







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 © 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 <[email protected]>
 *
 * 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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
 * 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. */
#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. */
#endif /* TCL_MEM_DEBUG && TCL_THREADS */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

static void             TclThreadFinalizeContLines(ClientData 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
				 * 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
				 * 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







|
















|













|






|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
 * 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 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. */
#endif /* TCL_MEM_DEBUG && TCL_THREADS */
} ThreadSpecificData;

static Tcl_ThreadDataKey dataKey;

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 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
				 * 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
221
222
223
224
225
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240

241
242
243
244
245
246
247

248
249
250
251
252
253
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/*
 * 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 = {
    "boolean",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    NULL,			/* updateStringProc */
    TclSetBooleanFromAny		/* setFromAnyProc */

};
const Tcl_ObjType tclDoubleType = {
    "double",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    UpdateStringOfDouble,	/* updateStringProc */
    SetDoubleFromAny		/* setFromAnyProc */

};
const Tcl_ObjType tclIntType = {
    "int",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    UpdateStringOfInt,		/* updateStringProc */
    SetIntFromAny		/* setFromAnyProc */

};
const Tcl_ObjType tclBignumType = {
    "bignum",			/* name */
    FreeBignum,			/* freeIntRepProc */
    DupBignum,			/* dupIntRepProc */
    UpdateStringOfBignum,	/* updateStringProc */
    NULL			/* setFromAnyProc */

};

/*
 * The structure below defines the Tcl obj hash key type.
 */

const Tcl_HashKeyType tclObjHashKeyType = {
    TCL_HASH_KEY_TYPE_VERSION,	/* version */
    0,				/* flags */
    TclHashObjKey,		/* hashKeyProc */
    TclCompareObjKeys,		/* compareKeysProc */
    AllocObjEntry,		/* allocEntryProc */
    TclFreeObjEntry		/* freeEntryProc */
};

/*







|




|
>

|




|
>






|
>






|
>








|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
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= {
    "boolean",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    NULL,			/* updateStringProc */
    TclSetBooleanFromAny,	/* setFromAnyProc */
    TCL_OBJTYPE_V1(TclLengthOne)
};
const Tcl_ObjType tclDoubleType= {
    "double",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    UpdateStringOfDouble,	/* updateStringProc */
    SetDoubleFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V1(TclLengthOne)
};
const Tcl_ObjType tclIntType = {
    "int",			/* name */
    NULL,			/* freeIntRepProc */
    NULL,			/* dupIntRepProc */
    UpdateStringOfInt,		/* updateStringProc */
    SetIntFromAny,		/* setFromAnyProc */
    TCL_OBJTYPE_V1(TclLengthOne)
};
const Tcl_ObjType tclBignumType = {
    "bignum",			/* name */
    FreeBignum,			/* freeIntRepProc */
    DupBignum,			/* dupIntRepProc */
    UpdateStringOfBignum,	/* updateStringProc */
    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 */
    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
 */

Tcl_ObjType tclCmdNameType = {
    "cmdName",			/* name */
    FreeCmdNameInternalRep,	/* freeIntRepProc */
    DupCmdNameInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    SetCmdNameFromAny		/* setFromAnyProc */

};

/*
 * 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
				 * 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
				 * 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;













/*
 *-------------------------------------------------------------------------
 *
 * TclInitObjectSubsystem --
 *
 *	This function is invoked to perform once-only initialization of the







|
>




















|




|











>
>
>
>
>
>
>
>
>
>
>
>







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
 */

Tcl_ObjType tclCmdNameType = {
    "cmdName",			/* name */
    FreeCmdNameInternalRep,	/* freeIntRepProc */
    DupCmdNameInternalRep,	/* dupIntRepProc */
    NULL,			/* updateStringProc */
    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). */
    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. */
    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
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(&tclCmdNameType);
    Tcl_RegisterObjType(&tclRegexpType);







<







373
374
375
376
377
378
379

380
381
382
383
384
385
386
TclInitObjSubsystem(void)
{
    Tcl_MutexLock(&tableMutex);
    typeTableInitialized = 1;
    Tcl_InitHashTable(&typeTable, TCL_STRING_KEYS);
    Tcl_MutexUnlock(&tableMutex);


    Tcl_RegisterObjType(&tclDoubleType);
    Tcl_RegisterObjType(&tclStringType);
    Tcl_RegisterObjType(&tclListType);
    Tcl_RegisterObjType(&tclDictType);
    Tcl_RegisterObjType(&tclByteCodeType);
    Tcl_RegisterObjType(&tclCmdNameType);
    Tcl_RegisterObjType(&tclRegexpType);
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
 * TIP #280
 *----------------------------------------------------------------------
 */

ContLineLoc *
TclContinuationsEnter(
    Tcl_Obj *objPtr,
    int num,
    int *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));

    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.
	 *
	 * 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));
    clLocPtr->loc[num] = CLL_END;       /* Sentinel */
    Tcl_SetHashValue(hPtr, clLocPtr);

    return clLocPtr;
}

/*







|
|





|











|















|







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
 * TIP #280
 *----------------------------------------------------------------------
 */

ContLineLoc *
TclContinuationsEnter(
    Tcl_Obj *objPtr,
    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 + 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 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(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
 * TIP #280
 *----------------------------------------------------------------------
 */

void
TclContinuationsEnterDerived(
    Tcl_Obj *objPtr,
    int start,
    int *clNext)
{
    size_t length;
    int end, num;
    int *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







|
|

|
|
|







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
 * TIP #280
 *----------------------------------------------------------------------
 */

void
TclContinuationsEnterDerived(
    Tcl_Obj *objPtr,
    Tcl_Size start,
    Tcl_Size *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

    /*
     * And generate the table from the slice, if it was not empty.
     */

    num = wordCLLast - clNext;
    if (num) {
	int i;
	ContLineLoc *clLocPtr = TclContinuationsEnter(objPtr, num, clNext);

	/*
	 * Re-base the locations.
	 */

	for (i=0 ; i<num ; i++) {







|







650
651
652
653
654
655
656
657
658
659
660
661
662
663
664

    /*
     * And generate the table from the slice, if it was not empty.
     */

    num = wordCLLast - clNext;
    if (num) {
	Tcl_Size i;
	ContLineLoc *clLocPtr = TclContinuationsEnter(objPtr, num, clNext);

	/*
	 * Re-base the locations.
	 */

	for (i=0 ; i<num ; i++) {
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
 *
 * TIP #280
 *----------------------------------------------------------------------
 */

static void
TclThreadFinalizeContLines(
    TCL_UNUSED(ClientData))
{
    /*
     * Release the hashtable tracking invisible continuation lines.
     */

    ThreadSpecificData *tsdPtr = TclGetContLineTable();
    Tcl_HashEntry *hPtr;







|







762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
 *
 * TIP #280
 *----------------------------------------------------------------------
 */

static void
TclThreadFinalizeContLines(
    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
    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;

    /*
     * Get the test for a valid list out of the way first.
     */

    if (TclListObjLength(interp, objPtr, &numElems) != TCL_OK) {
	return TCL_ERROR;







|







848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
    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;
    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
     * 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);
	}
	return TCL_ERROR;
    }

    return typePtr->setFromAnyProc(interp, objPtr);
}








|







946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
     * 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", (void *)NULL);
	}
	return TCL_ERROR;
    }

    return typePtr->setFromAnyProc(interp, objPtr);
}

968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
    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);
	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",







|







984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
    Tcl_HashEntry *hPtr;
    Tcl_HashTable *tablePtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    tablePtr = tsdPtr->objThreadMap;

    if (tablePtr != NULL) {
	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
/*
 *----------------------------------------------------------------------
 *
 * 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
 *	when compiling without TCL_MEM_DEBUG.
 *
 * Results:
 *	The Tcl_Obj struct members are initialized.
 *
 * Side effects:
 *	None.







|







1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
/*
 *----------------------------------------------------------------------
 *
 * 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. 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
    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);

#if TCL_THREADS
    /*
     * Add entry to a thread local map used to check if a Tcl_Obj was
     * allocated by the currently executing thread.
     */








|







1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
    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;
    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
#else /* if not TCL_MEM_DEBUG */

Tcl_Obj *
Tcl_DbNewObj(
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
{


    return Tcl_NewObj();
}
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 * TclAllocateFreeObjects --







>
>
|







1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
#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 objPtr;
}
#endif /* TCL_MEM_DEBUG */

/*
 *----------------------------------------------------------------------
 *
 * TclAllocateFreeObjects --
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
	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);
	if (hPtr) {
	    /*
	     * As the Tcl_Obj is going to be deleted we remove the entry.
	     */

	    ObjData *objData = (ObjData *)Tcl_GetHashValue(hPtr);








|







1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
	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, 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

    /*
     * 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) {
	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.
     */







|







1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329

    /*
     * 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 < -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
	TclIncrObjsFreed();
	ObjDeletionLock(context);
	while (ObjOnStack(context)) {
	    Tcl_Obj *objToFree;

	    PopObjToDelete(context, objToFree);
	    TCL_DTRACE_OBJ_FREE(objToFree);
	    TclFreeIntRep(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
     * which we crash (if we where to access the uninitialized hashtable).
     */

    {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
        Tcl_HashEntry *hPtr;








|















|







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
	TclIncrObjsFreed();
	ObjDeletionLock(context);
	while (ObjOnStack(context)) {
	    Tcl_Obj *objToFree;

	    PopObjToDelete(context, objToFree);
	    TCL_DTRACE_OBJ_FREE(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 uninitialized memory block upon
     * which we crash (if we where to access the uninitialized hashtable).
     */

    {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
        Tcl_HashEntry *hPtr;

1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457

    /*
     * 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
     * which we crash (if we where to access the uninitialized hashtable).
     */

    {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
        Tcl_HashEntry *hPtr;








|







1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475

    /*
     * 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 uninitialized memory block upon
     * which we crash (if we where to access the uninitialized hashtable).
     */

    {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
        Tcl_HashEntry *hPtr;

1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
    Tcl_Obj *dupPtr,
    Tcl_Obj *objPtr)
{
    if (Tcl_IsShared(dupPtr)) {
	Tcl_Panic("%s called with shared object", "TclSetDuplicateObj");
    }
    TclInvalidateStringRep(dupPtr);
    TclFreeIntRep(dupPtr);
    SetDuplicateObj(dupPtr, objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetString --







|







1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
    Tcl_Obj *dupPtr,
    Tcl_Obj *objPtr)
{
    if (Tcl_IsShared(dupPtr)) {
	Tcl_Panic("%s called with shared object", "TclSetDuplicateObj");
    }
    TclInvalidateStringRep(dupPtr);
    TclFreeInternalRep(dupPtr);
    SetDuplicateObj(dupPtr, objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetString --
1580
1581
1582
1583
1584
1585
1586

1587
1588
1589
1590
1591
1592
1593
 * Side effects:
 *	May call the object's updateStringProc to update the string
 *	representation from the internal representation.
 *
 *----------------------------------------------------------------------
 */


char *
Tcl_GetString(
    Tcl_Obj *objPtr)	/* Object whose string rep byte pointer should
				 * be returned. */
{
    if (objPtr->bytes == NULL) {
	/*







>







1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
 * 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
    }
    return objPtr->bytes;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetStringFromObj --
 *
 *	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.
 *
 *----------------------------------------------------------------------
 */



char *
Tcl_GetStringFromObj(
    Tcl_Obj *objPtr,	/* Object whose string rep byte pointer should
				 * be returned. */
    int *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







|



















>
>

|


|







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
    }
    return objPtr->bytes;
}

/*
 *----------------------------------------------------------------------
 *
 * 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 *
TclGetStringFromObj(
    Tcl_Obj *objPtr,	/* Object whose string rep byte pointer should
				 * be returned. */
    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
		|| 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;













































    }
    return objPtr->bytes;
}

/*
 *----------------------------------------------------------------------
 *







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
		|| objPtr->bytes[objPtr->length] != '\0') {
	    Tcl_Panic("UpdateStringProc for type '%s' "
		    "failed to create a valid string rep",
		    objPtr->typePtr->name);
	}
    }
    if (lengthPtr != NULL) {
	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
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) {



	    objPtr->bytes = (char *)Tcl_AttemptAlloc(numBytes + 1);
	    if (objPtr->bytes == NULL) {
		return NULL;
	    }

	    if (bytes) {
		/* Copy */
		memcpy(objPtr->bytes, bytes, numBytes);

		objPtr->length = numBytes;
	    }





	} else {

	    TclInitStringRep(objPtr, NULL, 0);


	}

    } else {




	/* objPtr->bytes != NULL bytes == NULL - Truncate */

	objPtr->bytes = (char *)Tcl_Realloc(objPtr->bytes, numBytes + 1);


	objPtr->length = numBytes;

    }

    /* Terminate */
    objPtr->bytes[objPtr->length] = '\0';


    return objPtr->bytes;
}

/*
 *----------------------------------------------------------------------
 *







<

<
<
>
|
>
>
>

|
<
<
>
|
<
|
>
|

>
>
>
>
>

>
|
>
>
|
>

>
>
>
>
|
>
|
>
>
|
>
|
|
<
<
>







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
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);


    if (objPtr->bytes == NULL) {


	/* Start with no string rep */
	if (numBytes == 0) {
	    TclInitEmptyStringRep(objPtr);
	    return objPtr->bytes;
	} else {
	    objPtr->bytes = (char *)Tcl_AttemptAlloc(numBytes + 1);
	    if (objPtr->bytes) {


		objPtr->length = numBytes;
		if (bytes) {

		    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);
	    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);
	    return objPtr->bytes;
	} else {
	    objPtr->bytes = (char *)Tcl_AttemptRealloc(objPtr->bytes,
		    numBytes + 1);
	    if (objPtr->bytes) {
		objPtr->length = numBytes;
		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
{
    return TclHasStringRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_StoreIntRep --
 *
 *	This function is 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 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_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 */
{
    /* Clear out any existing IntRep ( "shimmer" ) */
    TclFreeIntRep(objPtr);

    /* When irPtr == NULL, just leave objPtr with no IntRep for typePtr */
    if (irPtr) {
	/* Copy the new IntRep into place */
	objPtr->internalRep = *irPtr;

	/* Set the type to match */
	objPtr->typePtr = typePtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FetchIntRep --
 *
 *	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
 *	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_Obj *objPtr,		/* Object to fetch from. */
    const Tcl_ObjType *typePtr)	/* Requested type */
{
    return TclFetchIntRep(objPtr, typePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FreeIntRep --
 *
 *	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_Obj *objPtr)	/* Object whose internal rep should be freed. */
{
    TclFreeIntRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */


int
Tcl_GetBooleanFromObj(
    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,	/* The object from which to get boolean. */

    int *boolPtr)	/* Place to store resulting boolean. */
{














    do {
	if (objPtr->typePtr == &tclIntType || objPtr->typePtr == &tclBooleanType) {
	    *boolPtr = (objPtr->internalRep.wideValue != 0);
	    return TCL_OK;

	}
	if (objPtr->typePtr == &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
	     * 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;





	}
	if (objPtr->typePtr == &tclBignumType) {

	    *boolPtr = 1;

	    return TCL_OK;
	}
    } while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK ==
	    TclParseNumber(interp, objPtr, "boolean value", NULL,-1,NULL,0)));

    return TCL_ERROR;
}











/*
 *----------------------------------------------------------------------
 *
 * TclSetBooleanFromAny --
 *
 *	Attempt to generate a boolean internal form for the Tcl object
 *	"objPtr".







|

|
|


|













|


|

|
|

|

|










|





|









|
|



|





|














|


|





|










|




>

|


>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
<
>

|


|










|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
<
>
|
>



|
>



>
>
>
>
>
>
>
>
>
>







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
{
    return TclHasStringRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_StoreInternalRep --
 *
 *	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 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_StoreInternalRep(
    Tcl_Obj *objPtr,		/* Object whose internal rep should be set. */
    const Tcl_ObjType *typePtr,	/* New type for the object */
    const Tcl_ObjInternalRep *irPtr)	/* New internalrep for the object */
{
    /* Clear out any existing internalrep ( "shimmer" ) */
    TclFreeInternalRep(objPtr);

    /* When irPtr == NULL, just leave objPtr with no internalrep for typePtr */
    if (irPtr) {
	/* Copy the new internalrep into place */
	objPtr->internalRep = *irPtr;

	/* Set the type to match */
	objPtr->typePtr = typePtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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_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_ObjInternalRep *
Tcl_FetchInternalRep(
    Tcl_Obj *objPtr,		/* Object to fetch from. */
    const Tcl_ObjType *typePtr)	/* Requested type */
{
    return TclFetchInternalRep(objPtr, typePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * 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_FreeInternalRep(
    Tcl_Obj *objPtr)	/* Object whose internal rep should be freed. */
{
    TclFreeInternalRep(objPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * 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 internalrep of *objPtr may be changed.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_GetBoolFromObj
int
Tcl_GetBoolFromObj(
    Tcl_Interp *interp,         /* Used for error reporting if not NULL. */
    Tcl_Obj *objPtr,	/* The object from which to get boolean. */
    int flags,
    char *charPtr)	/* Place to store resulting boolean. */
{
    int result;

    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 (TclHasInternalRep(objPtr, &tclIntType) || TclHasInternalRep(objPtr, &tclBooleanType)) {
	    result = (objPtr->internalRep.wideValue != 0);

	    goto boolEnd;
	}
	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    /*
	     * Caution: Don't be tempted to check directly for the "double"
	     * 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;
	    }
	    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");
		    }

		}
		*charPtr = result;
	    }
	    return TCL_OK;
	}
    } while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK ==
	    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
    /*
     * 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 ((Tcl_WideUInt)objPtr->internalRep.wideValue < 2) {
		return TCL_OK;
	    }
	    goto badBoolean;
	}

	if (objPtr->typePtr == &tclBignumType) {
	    goto badBoolean;
	}

	if (objPtr->typePtr == &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_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);
    }
    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);

    if ((length == 0) || (length > 5)) {
	/*
         * Longest valid boolean string rep. is "false".
         */

	return TCL_ERROR;
    }

    switch (str[0]) {
    case '0':
	if (length == 1) {







|






|



|










|
|






|










|
|

|

|
|







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
    /*
     * 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 (TclHasInternalRep(objPtr, &tclIntType)) {
	    if ((Tcl_WideUInt)objPtr->internalRep.wideValue < 2) {
		return TCL_OK;
	    }
	    goto badBoolean;
	}

	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    goto badBoolean;
	}

	if (TclHasInternalRep(objPtr, &tclDoubleType)) {
	    goto badBoolean;
	}
    }

    if (ParseBoolean(objPtr) == TCL_OK) {
	return TCL_OK;
    }

  badBoolean:
    if (interp != NULL) {
	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", (void *)NULL);
    }
    return TCL_ERROR;
}

static int
ParseBoolean(
    Tcl_Obj *objPtr)	/* The object to parse/convert. */
{
    int newBool;
    char lowerCase[6];
    Tcl_Size i, length;
    const char *str = Tcl_GetStringFromObj(objPtr, &length);

    if ((length < 1) || (length > 5)) {
	/*
	 * 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
    /*
     * 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);
    objPtr->internalRep.wideValue = newBool;
    objPtr->typePtr = &tclBooleanType;
    return TCL_OK;

  numericBoolean:
    TclFreeIntRep(objPtr);
    objPtr->internalRep.wideValue = newBool;
    objPtr->typePtr = &tclIntType;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|





|







2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
    /*
     * 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:
    TclFreeInternalRep(objPtr);
    objPtr->internalRep.wideValue = newBool;
    objPtr->typePtr = &tclBooleanType;
    return TCL_OK;

  numericBoolean:
    TclFreeInternalRep(objPtr);
    objPtr->internalRep.wideValue = newBool;
    objPtr->typePtr = &tclIntType;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
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
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. */
{
    do {
	if (objPtr->typePtr == &tclDoubleType) {
	    if (TclIsNaN(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);
		}
		return TCL_ERROR;
	    }
	    *dblPtr = (double) objPtr->internalRep.doubleValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclIntType) {
	    *dblPtr = (double) objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclBignumType) {
	    mp_int big;

	    TclUnpackBignum(objPtr, big);
	    *dblPtr = TclBignumToDouble(&big);
	    return TCL_OK;
	}
    } while (SetDoubleFromAny(interp, objPtr) == TCL_OK);







|
|




|






|



|







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
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. */
{
    do {
	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",
                            (void *)NULL);
		}
		return TCL_ERROR;
	    }
	    *dblPtr = (double) objPtr->internalRep.doubleValue;
	    return TCL_OK;
	}
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    *dblPtr = (double) objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (TclHasInternalRep(objPtr, &tclBignumType)) {
	    mp_int big;

	    TclUnpackBignum(objPtr, big);
	    *dblPtr = TclBignumToDouble(&big);
	    return TCL_OK;
	}
    } while (SetDoubleFromAny(interp, objPtr) == TCL_OK);
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391

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);

    Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, dst);
    (void) Tcl_InitStringRep(objPtr, NULL, strlen(dst));
}

/*
 *----------------------------------------------------------------------







|







2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516

static void
UpdateStringOfDouble(
    Tcl_Obj *objPtr)	/* Double obj with string rep to update. */
{
    char *dst = Tcl_InitStringRep(objPtr, NULL, TCL_DOUBLE_SPACE);

    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

2446
2447
2448
2449
2450
2451
2452

    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";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
	}
	return TCL_ERROR;
    }
    *intPtr = (int) l;
    return TCL_OK;
#endif
}


/*
 *----------------------------------------------------------------------
 *
 * SetIntFromAny --
 *
 *	Attempts to force the internal representation for a Tcl object to







|

|







>







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

    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";
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
	    Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (void *)NULL);
	}
	return TCL_ERROR;
    }
    *intPtr = (int) l;
    return TCL_OK;
#endif
}


/*
 *----------------------------------------------------------------------
 *
 * SetIntFromAny --
 *
 *	Attempts to force the internal representation for a Tcl object to
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476

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);
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfInt --
 *







|







2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602

static int
SetIntFromAny(
    Tcl_Interp *interp,		/* Tcl interpreter */
    Tcl_Obj *objPtr)		/* Pointer to the object to convert */
{
    Tcl_WideInt w;
    return TclGetWideIntFromObj(interp, objPtr, &w);
}

/*
 *----------------------------------------------------------------------
 *
 * UpdateStringOfInt --
 *
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504

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);
    (void) Tcl_InitStringRep(objPtr, NULL,
	    TclFormatInt(dst, objPtr->internalRep.wideValue));
}

/*
 *----------------------------------------------------------------------
 *







|







2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630

static void
UpdateStringOfInt(
    Tcl_Obj *objPtr)	/* Int object whose string rep to update. */
{
    char *dst = Tcl_InitStringRep( objPtr, NULL, TCL_INTEGER_SPACE);

    TclOOM(dst, TCL_INTEGER_SPACE + 1);
    (void) Tcl_InitStringRep(objPtr, NULL,
	    TclFormatInt(dst, objPtr->internalRep.wideValue));
}

/*
 *----------------------------------------------------------------------
 *
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
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. */
{
    do {
#ifdef TCL_WIDE_INT_IS_LONG
	if (objPtr->typePtr == &tclIntType) {
	    *longPtr = objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
#else
	if (objPtr->typePtr == &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;
		return TCL_OK;
	    }
	    goto tooLarge;
	}
#endif
	if (objPtr->typePtr == &tclDoubleType) {
	    if (interp != NULL) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "expected integer but got \"%s\"",
                        TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
	    }
	    return TCL_ERROR;
	}
	if (objPtr->typePtr == &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;
			return TCL_OK;
		    }
		} else {
		    if (value <= (unsigned long)ULONG_MAX) {
			*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);
	    }
	    return TCL_ERROR;
	}
    } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
	    TCL_PARSE_INTEGER_ONLY)==TCL_OK);
    return TCL_ERROR;
}







|




|












|





|




|



|




















|




|













|







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
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. */
{
    do {
#ifdef TCL_WIDE_INT_IS_LONG
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    *longPtr = objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
#else
	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;
		return TCL_OK;
	    }
	    goto tooLarge;
	}
#endif
	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", (void *)NULL);
	    }
	    return TCL_ERROR;
	}
	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);
			return TCL_OK;
		    }
		} else {
		    if (value <= (unsigned long)ULONG_MAX) {
			*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, (void *)NULL);
	    }
	    return TCL_ERROR;
	}
    } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
	    TCL_PARSE_INTEGER_ONLY)==TCL_OK);
    return TCL_ERROR;
}
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
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. */
{
    do {
	if (objPtr->typePtr == &tclIntType) {
	    *wideIntPtr = objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclDoubleType) {
	    if (interp != NULL) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "expected integer but got \"%s\"",
                        TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
	    }
	    return TCL_ERROR;
	}
	if (objPtr->typePtr == &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;
			return TCL_OK;
		    }
		} else {
		    if (value <= (Tcl_WideUInt)WIDE_MAX) {
			*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);




















































































	    }
	    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







|



|




|



|


















|




|









|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|







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
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. */
{
    do {
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    *wideIntPtr = objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	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", (void *)NULL);
	    }
	    return TCL_ERROR;
	}
	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);
			return TCL_OK;
		    }
		} else {
		    if (value <= (Tcl_WideUInt)WIDE_MAX) {
			*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, (void *)NULL);
	    }
	    return TCL_ERROR;
	}
    } 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", (void *)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, (void *)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
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) {
	    *wideIntPtr = objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclDoubleType) {
	    if (interp != NULL) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "expected integer but got \"%s\"",
                        TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
	    }
	    return TCL_ERROR;
	}
	if (objPtr->typePtr == &tclBignumType) {
	    mp_int big;
	    mp_err err;

	    Tcl_WideUInt value = 0, scratch;
	    size_t numBytes;
	    unsigned char *bytes = (unsigned char *) &scratch;








|



|




|



|







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
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 (TclHasInternalRep(objPtr, &tclIntType)) {
	    *wideIntPtr = objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	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", (void *)NULL);
	    }
	    return TCL_ERROR;
	}
	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
	    mp_clear(&big);
	    return TCL_OK;
	}
    } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
	    TCL_PARSE_INTEGER_ONLY)==TCL_OK);
    return TCL_ERROR;
}



































/*
 *----------------------------------------------------------------------
 *
 * FreeBignum --
 *
 *	This function frees the internal rep of a bignum.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    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
 *
 *	This function duplicates the internal rep of a bignum.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	The destination object receies a copy of the source object
 *
 *----------------------------------------------------------------------
 */

static void
DupBignum(
    Tcl_Obj *srcPtr,







|







3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
 *
 *	This function duplicates the internal rep of a bignum.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	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

    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.
 *
 * Results:
 *	Returns the newly created object.
 *
 * Side effects:
 *	The bignum value is cleared, since ownership has transferred to Tcl.
 *







<







|







3265
3266
3267
3268
3269
3270
3271

3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286

    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");
    }

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_NewBignumObj --
 *
 *	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
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 (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 */
		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);
		}
	    }
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclIntType) {
	    if (mp_init_i64(bignumValue,
		    objPtr->internalRep.wideValue) != MP_OKAY) {
		return TCL_ERROR;
	    }
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclDoubleType) {
	    if (interp != NULL) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "expected integer but got \"%s\"",
                        TclGetString(objPtr)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
	    }
	    return TCL_ERROR;
	}
    } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
	    TCL_PARSE_INTEGER_ONLY)==TCL_OK);
    return TCL_ERROR;
}







|









|









|




|






|




|







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
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 (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 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) {
		    TclInitEmptyStringRep(objPtr);
		}
	    }
	    return TCL_OK;
	}
	if (TclHasInternalRep(objPtr, &tclIntType)) {
	    if (mp_init_i64(bignumValue,
		    objPtr->internalRep.wideValue) != MP_OKAY) {
		return TCL_ERROR;
	    }
	    return TCL_OK;
	}
	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", (void *)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
 *	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'
 *	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







|







3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
 *	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 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
    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);
    } else {
	TclSetIntObj(objPtr, (Tcl_WideInt)value);
    }
    mp_clear(bignumValue);
    return;
  tooLargeForWide:
    TclInvalidateStringRep(objPtr);
    TclFreeIntRep(objPtr);
    TclSetBignumIntRep(objPtr, bignumValue);
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetBignumIntRep --
 *
 *	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(
    Tcl_Obj *objPtr,
    void *big)
{
    mp_int *bignumValue = (mp_int *)big;
    objPtr->typePtr = &tclBignumType;
    PACK_BIGNUM(*bignumValue, objPtr);








|







|
|





|















|







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
    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));
    } else {
	TclSetIntObj(objPtr, (Tcl_WideInt)value);
    }
    mp_clear(bignumValue);
    return;
  tooLargeForWide:
    TclInvalidateStringRep(objPtr);
    TclFreeInternalRep(objPtr);
    TclSetBignumInternalRep(objPtr, bignumValue);
}

/*
 *----------------------------------------------------------------------
 *
 * 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
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
    bignumValue->alloc = bignumValue->used = 0;
    bignumValue->sign = MP_NEG;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetNumberFromObj --
 *
 *      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_Interp *interp,
    Tcl_Obj *objPtr,
    ClientData *clientDataPtr,
    int *typePtr)
{
    do {
	if (objPtr->typePtr == &tclDoubleType) {
	    if (TclIsNaN(objPtr->internalRep.doubleValue)) {
		*typePtr = TCL_NUMBER_NAN;
	    } else {
		*typePtr = TCL_NUMBER_DOUBLE;
	    }
	    *clientDataPtr = &objPtr->internalRep.doubleValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &tclIntType) {
	    *typePtr = TCL_NUMBER_INT;
	    *clientDataPtr = &objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	if (objPtr->typePtr == &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;
	}
    } while (TCL_OK ==
	    TclParseNumber(interp, objPtr, "number", NULL, -1, NULL, 0));
    return TCL_ERROR;
}





































/*
 *----------------------------------------------------------------------
 *
 * Tcl_IncrRefCount --
 *
 *	Increments the reference count of the object.







|

















|


|



|
|







|




|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    bignumValue->alloc = bignumValue->used = 0;
    bignumValue->sign = MP_NEG;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
Tcl_GetNumberFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    void **clientDataPtr,
    int *typePtr)
{
    do {
	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 (TclHasInternalRep(objPtr, &tclIntType)) {
	    *typePtr = TCL_NUMBER_INT;
	    *clientDataPtr = &objPtr->internalRep.wideValue;
	    return TCL_OK;
	}
	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;
	}
    } 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", (void *)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
 *----------------------------------------------------------------------
 *
 * Tcl_DecrRefCount --
 *
 *	Decrements the reference count of the object.
 *
 * Results:
 *	None.
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_DecrRefCount
void
Tcl_DecrRefCount(
    Tcl_Obj *objPtr)	/* The object we are releasing a reference to. */
{
    if (objPtr->refCount-- <= 1) {
	TclFreeObj(objPtr);
    }
}























/*
 *----------------------------------------------------------------------
 *
 * 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);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DbIncrRefCount --
 *







|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



















|







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
 *----------------------------------------------------------------------
 *
 * Tcl_DecrRefCount --
 *
 *	Decrements the reference count of the object.
 *
 * Results:
 *	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);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DbIncrRefCount --
 *
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
    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) {
	fprintf(stderr, "file = %s, line = %d\n", file, line);
	fflush(stderr);
	Tcl_Panic("incrementing refCount of previously disposed object");
    }

#if TCL_THREADS
    /*







|







3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
    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 == FREEDREFCOUNTFILLER) {
	fprintf(stderr, "file = %s, line = %d\n", file, line);
	fflush(stderr);
	Tcl_Panic("incrementing refCount of previously disposed object");
    }

#if TCL_THREADS
    /*
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
    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) {
	fprintf(stderr, "file = %s, line = %d\n", file, line);
	fflush(stderr);
	Tcl_Panic("decrementing refCount of previously disposed object");
    }

#if TCL_THREADS
    /*







|







3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
    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 == FREEDREFCOUNTFILLER) {
	fprintf(stderr, "file = %s, line = %d\n", file, line);
	fflush(stderr);
	Tcl_Panic("decrementing refCount of previously disposed object");
    }

#if TCL_THREADS
    /*
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
				 * debugging. */
#else
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
#endif
{
#ifdef TCL_MEM_DEBUG
    if (objPtr->refCount == 0x61616161) {
	fprintf(stderr, "file = %s, line = %d\n", file, line);
	fflush(stderr);
	Tcl_Panic("checking whether previously disposed object is shared");
    }

#if TCL_THREADS
    /*







|







3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
				 * debugging. */
#else
    TCL_UNUSED(const char *) /*file*/,
    TCL_UNUSED(int) /*line*/)
#endif
{
#ifdef TCL_MEM_DEBUG
    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
    /*
3783
3784
3785
3786
3787
3788
3789
3790


3791
3792
3793
3794
3795
3796
3797
    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;


    */

    /*
     * Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
     * in a register.
     */








|
>
>







4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
    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;
       }
    */

    /*
     * 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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TCL_HASH_TYPE
TclHashObjKey(
    TCL_UNUSED(Tcl_HashTable *),
    void *keyPtr)		/* Key from which to compute hash value. */
{
    Tcl_Obj *objPtr = (Tcl_Obj *)keyPtr;

    const char *string = TclGetString(objPtr);
    size_t length = objPtr->length;
    TCL_HASH_TYPE 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:







|





>
|
<
|







4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175

4176
4177
4178
4179
4180
4181
4182
4183
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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 = Tcl_GetStringFromObj(objPtr, &length);

    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
     *
     * See also HashStringKey in tclHash.c.
     * See also HashString in tclLiteral.c.
     *
     * See [tcl-Feature Request #2958832]
     */

    if (length) {
	result = UCHAR(*string);
	while (--length) {
	    result += (result << 3) + UCHAR(*++string);
	}
    }
    return result;
}







|







4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
     *
     * See also HashStringKey in tclHash.c.
     * See also HashString in tclLiteral.c.
     *
     * See [tcl-Feature Request #2958832]
     */

    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
     * 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 ((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;
            }
        }
    }








|









|







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
     * 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 (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 ((resPtr->refNsPtr == NULL)
		    || ((refNsPtr == resPtr->refNsPtr)
                    && (resPtr->refNsId == refNsPtr->nsId)
                    && (resPtr->refNsCmdEpoch == refNsPtr->cmdRefEpoch))) {
                return (Tcl_Command) cmdPtr;
            }
        }
    }

4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
 *	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
 *	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.
 *
 *----------------------------------------------------------------------
 */








|







4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
 *	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. 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

	fillPtr->refNsPtr = currNsPtr;
	fillPtr->refNsId = currNsPtr->nsId;
	fillPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
    }

    if (resPtr == NULL) {
	TclFreeIntRep(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) {
	resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
	if (resPtr != NULL && resPtr->cmdPtr == cmdPtr) {
	    return;
	}
    }

    SetCmdNameObj(interp, objPtr, cmdPtr, NULL);







|


















|







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

	fillPtr->refNsPtr = currNsPtr;
	fillPtr->refNsId = currNsPtr->nsId;
	fillPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
    }

    if (resPtr == NULL) {
	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 (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
     */

    if (cmdPtr == NULL || !TclRoutineHasName(cmdPtr)) {
	return TCL_ERROR;
    }

    resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
    if ((objPtr->typePtr == &tclCmdNameType) && (resPtr->refCount == 1)) {
	/*
	 * Re-use existing ResolvedCmdName struct when possible.
	 * Cleanup the old fields that need it.
	 */

	Command *oldCmdPtr = resPtr->cmdPtr;








|







4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
     */

    if (cmdPtr == NULL || !TclRoutineHasName(cmdPtr)) {
	return TCL_ERROR;
    }

    resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RepresentationCmd(
    TCL_UNUSED(ClientData),
    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,"
	    " 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) {
	    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);
	}







|

















|





|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_RepresentationCmd(
    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_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 (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);
	}

Changes to generic/tclOptimize.c.

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.
 *
 * 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"





|







1
2
3
4
5
6
7
8
9
10
11
12
13
/*
 * tclOptimize.c --
 *
 *	This file contains the bytecode optimizer.
 *
 * 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
static void		TrimUnreachable(CompileEnv *envPtr);

/*
 * Helper macros.
 */

#define DefineTargetAddress(tablePtr, address) \
    ((void) Tcl_CreateHashEntry((tablePtr), (void *) (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)








|







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), (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

static void
LocateTargetAddresses(
    CompileEnv *envPtr,
    Tcl_HashTable *tablePtr)
{
    unsigned char *currentInstPtr, *targetInstPtr;
    int isNew, i;

    Tcl_HashEntry *hPtr;
    Tcl_HashSearch hSearch;

    Tcl_InitHashTable(tablePtr, TCL_ONE_WORD_KEYS);

    /*
     * The starts of commands represent target addresses.







|
>







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;
    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

	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) {
		targetInstPtr = envPtr->codeStart + rangePtr->continueOffset;
		DefineTargetAddress(tablePtr, targetInstPtr);
	    }
	}
    }
}








|







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 != 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
    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) {
	    if (IsTargetAddress(&targets, currentInstPtr + size)) {
		break;
	    }
	    size += InstLength(INST_NOP);
	}
	if (IsTargetAddress(&targets, currentInstPtr + size)) {
	    continue;
	}
	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;

		(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;

		(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;
		break;
	    case INST_JUMP_FALSE1:
		blank = size;
		*(currentInstPtr + size) = INST_JUMP_TRUE1;
		break;
	    case INST_JUMP_TRUE4:
		blank = size;
		*(currentInstPtr + size) = INST_JUMP_FALSE4;
		break;
	    case INST_JUMP_FALSE4:
		blank = size;
		*(currentInstPtr + size) = INST_JUMP_TRUE4;
		break;
	    }
	    break;

	case INST_TRY_CVT_TO_NUMERIC:
	    switch (nextInst) {
	    case INST_JUMP_TRUE1:







|








|








|














|












|



|



|



|







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
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) {
	    if (IsTargetAddress(&targets, currentInstPtr + size)) {
		break;
	    }
	    size += InstLength(INST_NOP);
	}
	if (IsTargetAddress(&targets, currentInstPtr + size)) {
	    continue;
	}
	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));
		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));
		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;
		break;
	    case INST_JUMP_FALSE1:
		blank = size;
		currentInstPtr[size] = INST_JUMP_TRUE1;
		break;
	    case INST_JUMP_TRUE4:
		blank = size;
		currentInstPtr[size] = INST_JUMP_FALSE4;
		break;
	    case INST_JUMP_FALSE4:
		blank = size;
		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
		break;
	    }
	    break;
	}

	if (blank > 0) {
	    for (i=0 ; i<blank ; i++) {
		*(currentInstPtr + i) = INST_NOP;
	    }
	    size = blank;
	}
    }
    Tcl_DeleteHashTable(&targets);
}








|







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;
	    }
	    size = blank;
	}
    }
    Tcl_DeleteHashTable(&targets);
}

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
		}
		Tcl_CreateHashEntry(&jumps, INT2PTR(offset), &isNew);
		if (!isNew) {
		    offset = TclGetInt1AtPtr(currentInstPtr + 1);
		    break;
		}
		offset += delta;
		switch (*(currentInstPtr + offset)) {
		case INST_NOP:
		    delta = InstLength(INST_NOP);
		    continue;
		case INST_JUMP1:
		    delta = TclGetInt1AtPtr(currentInstPtr + offset + 1);
		    continue;
		case INST_JUMP4:







|







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]) {
		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
	    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)) {
		case INST_NOP:
		    offset += InstLength(INST_NOP);
		    continue;
		case INST_JUMP1:
		    offset += TclGetInt1AtPtr(currentInstPtr + offset + 1);
		    continue;
		case INST_JUMP4:







|







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]) {
		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
/*
 * 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.
 *
 * 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__)







|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
 * 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 © 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__)
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
 *
 * Side effects:
 *	Sets the panicProc variable.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetPanicProc(
    TCL_NORETURN1 Tcl_PanicProc *proc)
{
    panicProc = proc;
    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
 * a Tcl_Panic() call can never return and avoids lots of false positives.
 */

/* coverity[+kill] */
void
Tcl_Panic(
    const char *format,







|




|



















|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
 *
 * Side effects:
 *	Sets the panicProc variable.
 *
 *----------------------------------------------------------------------
 */

const char *
Tcl_SetPanicProc(
    TCL_NORETURN1 Tcl_PanicProc *proc)
{
    panicProc = proc;
    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 analyzer knows that
 * a Tcl_Panic() call can never return and avoids lots of false positives.
 */

/* coverity[+kill] */
void
Tcl_Panic(
    const char *format,

Changes to generic/tclParse.c.

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.
 * 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"







|
|







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 © 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
 * 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_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[] = {

    /*
     * 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_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,







>





|















|







29
30
31
32
33
34
35
36
37
38
39
40
41
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 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_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
    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,
			    Tcl_Parse *parsePtr);
static int		ParseTokens(const char *src, size_t numBytes, int mask,
			    int flags, Tcl_Parse *parsePtr);
static size_t		ParseWhiteSpace(const char *src, size_t numBytes,
			    int *incompletePtr, char *typePtr);
static size_t		ParseAllWhiteSpace(const char *src, size_t numBytes,
			    int *incompletePtr);
static int		ParseHex(const char *src, size_t numBytes,
			    int *resultPtr);

/*
 *----------------------------------------------------------------------
 *
 * TclParseInit --
 *







|
|

|

|

|

|







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, Tcl_Size numBytes);
static Tcl_Size		ParseComment(const char *src, Tcl_Size numBytes,
			    Tcl_Parse *parsePtr);
static int		ParseTokens(const char *src, Tcl_Size numBytes, int mask,
			    int flags, Tcl_Parse *parsePtr);
static Tcl_Size		ParseWhiteSpace(const char *src, Tcl_Size numBytes,
			    int *incompletePtr, char *typePtr);
static Tcl_Size		ParseAllWhiteSpace(const char *src, Tcl_Size numBytes,
			    int *incompletePtr);
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
 *----------------------------------------------------------------------
 */

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,
				 * 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;







|







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. */
    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

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,
				 * 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. */
    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;

    if (numBytes == TCL_INDEX_NONE && 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));







|















|




|

|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
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. */
    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. */
    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. */
    Tcl_Size scanned;

    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
	    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_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)
		    /* 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))







|

















|







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 == '{') {
	    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 */
		    && (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
	 * 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;
	    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()







|







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) {
	    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
		if (tokenPtr[i].type != TCL_TOKEN_TEXT) {
		    isLiteral = 0;
		    break;
		}
	    }

	    if (isLiteral) {

		int elemCount = 0, 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







>
|







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 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

		/*
		 * Step through the literal string, parsing and counting list
		 * elements.
		 */

		while (nextElem < listEnd) {
		    size_t size;

		    code = TclFindElement(NULL, nextElem, listEnd - nextElem,
			    &elemStart, &nextElem, &size, &literal);
		    if ((code != TCL_OK) || !literal) {
			break;
		    }
		    if (elemStart < listEnd) {







|







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) {
		    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
		} else {
		    /*
		     * Recalculate the number of Tcl_Tokens needed to store
		     * tokens representing the expanded list.
		     */

		    const char *listStart;
		    int growthNeeded = wordIndex + 2*elemCount
			    - parsePtr->numTokens;

		    parsePtr->numWords += elemCount - 1;
		    if (growthNeeded > 0) {
			TclGrowParseTokenArray(parsePtr, growthNeeded);
			tokenPtr = &parsePtr->tokenPtr[wordIndex];
		    }







|







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;
		    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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static size_t
ParseWhiteSpace(
    const char *src,		/* First character to parse. */
    size_t 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;







|


|







618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Size
ParseWhiteSpace(
    const char *src,		/* First character to parse. */
    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
 *
 * Results:
 *	Returns the number of bytes recognized as white space.
 *
 *----------------------------------------------------------------------
 */

static size_t
ParseAllWhiteSpace(
    const char *src,		/* First character to parse. */
    size_t 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);

	p += scanned;
	numBytes -= scanned;
    } while (numBytes && (*p == '\n') && (p++, --numBytes));
    return (p-src);
}

size_t
TclParseAllWhiteSpace(
    const char *src,		/* First character to parse. */
    size_t numBytes)		/* Max number of byes to scan */
{
    int dummy;
    return ParseAllWhiteSpace(src, numBytes, &dummy);
}

/*
 *----------------------------------------------------------------------







|


|






|







|


|







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 Tcl_Size
ParseAllWhiteSpace(
    const char *src,		/* First character to parse. */
    Tcl_Size numBytes,		/* Max number of byes to scan */
    int *incompletePtr)		/* Set true if parse is incomplete. */
{
    char type;
    const char *p = src;

    do {
	Tcl_Size scanned = ParseWhiteSpace(p, numBytes, incompletePtr, &type);

	p += scanned;
	numBytes -= scanned;
    } while (numBytes && (*p == '\n') && (p++, --numBytes));
    return (p-src);
}

Tcl_Size
TclParseAllWhiteSpace(
    const char *src,		/* First character to parse. */
    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
 *
 *----------------------------------------------------------------------
 */

int
ParseHex(
    const char *src,		/* First character to parse. */
    size_t 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;








|







724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
 *
 *----------------------------------------------------------------------
 */

int
ParseHex(
    const char *src,		/* First character to parse. */
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclParseBackslash(
    const char *src,		/* Points to the backslash character of a a
				 * backslash sequence. */
    size_t numBytes,		/* Max number of bytes to scan. */
    size_t *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 result;
    size_t count;
    char buf[4] = "";

    if (numBytes == 0) {
	if (readPtr != NULL) {
	    *readPtr = 0;
	}
	return 0;







|

|
|






|

|







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
				 * backslash sequence. */
    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;
    int unichar;
    int result;
    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
    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++;







<
<
<
<
<
<
<
<
<
<









<
<
<







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';










	}
	break;
    case 'U':
	count += ParseHex(p+1, (numBytes > 9) ? 8 : numBytes-2, &result);
	if (count == 2) {
	    /*
	     * No hexdigits -> This is just "U".
	     */
	    result = 'U';



	}
	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
	 * 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];

	    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 --







|














<
<
<
<







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[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);




    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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static size_t
ParseComment(
    const char *src,		/* First character to parse. */
    size_t 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);
	p += scanned;
	numBytes -= scanned;

	if ((numBytes == 0) || (*p != '#')) {
	    break;
	}
	if (parsePtr->commentStart == NULL) {







|


|








|







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 Tcl_Size
ParseComment(
    const char *src,		/* First character to parse. */
    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) {
	Tcl_Size scanned = ParseAllWhiteSpace(p, numBytes, &incomplete);
	p += scanned;
	numBytes -= scanned;

	if ((numBytes == 0) || (*p != '#')) {
	    break;
	}
	if (parsePtr->commentStart == 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
 *
 *----------------------------------------------------------------------
 */

static int
ParseTokens(
    const char *src,	/* First character to parse. */
    size_t 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;
    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







|













|







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
 *
 *----------------------------------------------------------------------
 */

static int
ParseTokens(
    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;
    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
		    && !(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;

	    if (noSubstVars) {
		tokenPtr->type = TCL_TOKEN_TEXT;
		tokenPtr->size = 1;
		parsePtr->numTokens++;
		src++;
		numBytes--;







|







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 == '$') {
	    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

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,
				 * 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) {
	numBytes = strlen(start);
    }
    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;







|














|







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 "$". */
    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 < 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
     *	  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 == '{') {

	src++;
	numBytes--;
	tokenPtr->type = TCL_TOKEN_TEXT;
	tokenPtr->start = src;
	tokenPtr->numComponents = 0;


	while (numBytes && (*src != '}')) {










	    numBytes--;
	    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;







>






>
|
>
>
>
>
>
>
>
>
>
>


>







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 && (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
	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,
		    TCL_SUBST_ALL, parsePtr)) {
		goto error;
	    }
	    if ((parsePtr->term == src+numBytes) || (*parsePtr->term != ')')){
		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;
	    }
	    src = parsePtr->term + 1;
	}
    }
    tokenPtr = &parsePtr->tokenPtr[varIndex];
    tokenPtr->size = src - tokenPtr->start;







|



|







>
>
>
>
>
>
>
>







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_BAD_ARRAY_INDEX,
		    TCL_SUBST_ALL, parsePtr)) {
		goto error;
	    }
	    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;
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
				 * 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) {
	TclStackFree(interp, parsePtr);
	return NULL;
    }

    if (termPtr != NULL) {
	*termPtr = start + parsePtr->tokenPtr->size;
    }







|







1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
				 * 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, 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

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,
				 * 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;
    size_t length;

    if (numBytes == TCL_INDEX_NONE && start) {
	numBytes = strlen(start);
    }
    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;







|
















|
<

|







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 {'. */
    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;
    Tcl_Size length, startIndex, level;


    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

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,
				 * 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) {
	numBytes = strlen(start);
    }
    if (!append) {
	TclParseInit(interp, start, numBytes, parsePtr);
    }
    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;







|














|







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 '"'. */
    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 < 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
 *----------------------------------------------------------------------
 */

void
TclSubstParse(
    Tcl_Interp *interp,
    const char *bytes,
    size_t numBytes,
    int flags,
    Tcl_Parse *parsePtr,
    Tcl_InterpState *statePtr)
{
    size_t 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







|




|







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,
    Tcl_Size numBytes,
    int flags,
    Tcl_Parse *parsePtr,
    Tcl_InterpState *statePtr)
{
    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
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.
				 * 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 */
    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;
    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
     * 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));
    }

    adjust = 0;
    result = NULL;
    for (; count>0 && code==TCL_OK ; count--, tokenPtr++) {
	Tcl_Obj *appendObj = NULL;
	const char *append = NULL;







|




|
|




















|
>
|














|
|
|

















|







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. */
    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 */
    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;
    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, 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 = (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
	     * 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;

		    if (result == 0) {
			clPos = 0;
		    } else {
			(void)TclGetStringFromObj(result, &clPos);
		    }

		    if (numCL >= maxNumCL) {
			maxNumCL *= 2;
			clPosition = (int *)Tcl_Realloc(clPosition,
				maxNumCL * sizeof(int));
		    }
		    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;

		TclAdvanceContinuations(&line, &clNextOuter,
			tokenPtr->start - outerScript);
		theline = line + adjust;
		code = TclEvalEx(interp, tokenPtr->start+1, tokenPtr->size-2,
			0, theline, clNextOuter, outerScript);








|









|
|

















|







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) {
		    Tcl_Size clPos;

		    if (result == 0) {
			clPos = 0;
		    } else {
			(void)TclGetStringFromObj(result, &clPos);
		    }

		    if (numCL >= maxNumCL) {
			maxNumCL *= 2;
			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}
		 */

		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
 *
 *----------------------------------------------------------------------
 */

static int
CommandComplete(
    const char *script,		/* Script to check. */
    size_t numBytes)		/* Number of bytes in script. */
{
    Tcl_Parse parse;
    const char *p, *end;
    int result;

    p = script;
    end = p + numBytes;







|







2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
 *
 *----------------------------------------------------------------------
 */

static int
CommandComplete(
    const char *script,		/* Script to check. */
    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
 *----------------------------------------------------------------------
 */

int
Tcl_CommandComplete(
    const char *script)		/* Script to check. */
{
    return CommandComplete(script, (int) strlen(script));
}

/*
 *----------------------------------------------------------------------
 *
 * TclObjCommandComplete --
 *







|







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, strlen(script));
}

/*
 *----------------------------------------------------------------------
 *
 * TclObjCommandComplete --
 *
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
 */

int
TclObjCommandComplete(
    Tcl_Obj *objPtr)		/* Points to object holding script to
				 * check. */
{
    size_t length;
    const char *script = TclGetStringFromObj(objPtr, &length);

    return CommandComplete(script, length);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|












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. */
{
    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
/*
 * Minimal set of shared macro definitions and declarations so that multiple
 * source files can make use of the parsing table in tclParse.c
 */

#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



#define CHAR_TYPE(c) tclCharTypeTable[(unsigned char)(c)]

MODULE_SCOPE const char tclCharTypeTable[];













>
>



|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Minimal set of shared macro definitions and declarations so that multiple
 * source files can make use of the parsing table in tclParse.c
 */

#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
#define TYPE_OPEN_PAREN		0x80
#define 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 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
/*
 * 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.
 *
 * 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 int		IsSeparatorOrNull(int ch);
static Tcl_Obj *	GetExtension(Tcl_Obj *pathPtr);
static int		MakePathFromNormalized(Tcl_Interp *interp,
			    Tcl_Obj *pathPtr);




/*
 * 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 */

};

/*
 * struct FsPath --
 *
 * Internal representation of a Tcl_Obj of fsPathType
 */







|



















|




>
>
>











|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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 © 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 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 */
    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
				 *  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
				 * 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 SETPATHOBJ(pathPtr,fsPathPtr) \
	do {							\
		Tcl_ObjIntRep ir;				\
		ir.twoPtrValue.ptr1 = (void *) (fsPathPtr);	\
		ir.twoPtrValue.ptr2 = NULL;			\
		Tcl_StoreIntRep((pathPtr), &fsPathType, &ir);	\
	} while (0)
#define PATHFLAGS(pathPtr) (PATHOBJ(pathPtr)->flags)

/*
 *---------------------------------------------------------------------------
 *
 * TclFSNormalizeAbsolutePath --







|




















|


|


|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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. */
    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 *) (TclFetchInternalRep((pathPtr), &fsPathType)->twoPtrValue.ptr1))
#define SETPATHOBJ(pathPtr,fsPathPtr) \
	do {							\
		Tcl_ObjInternalRep ir;				\
		ir.twoPtrValue.ptr1 = (void *) (fsPathPtr);	\
		ir.twoPtrValue.ptr2 = NULL;			\
		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
    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;

    dirSep = TclGetString(pathPtr);








    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;








>


>
>
>
>
>
>
>
|







140
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 : */
    } 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
		oldDirSep = dirSep;
	    }
	again:
	    if (IsSeparatorOrNull(dirSep[2])) {
		/*
		 * Need to skip '.' in the path.
		 */
		size_t 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;
		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)) {



		    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);

		    }

		    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_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 =







|



















|

















>
>
>
|

|
|
|
|
|
>










|
<







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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.
		 */
		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;
		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);

			/* 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_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
			    linkStr = TclGetStringFromObj(retVal, &curLen);

			    /*
			     * Convert to forward-slashes on windows.
			     */

			    if (tclPlatform == TCL_PLATFORM_WINDOWS) {
				size_t 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).

		     */


		    while (curLen-- > 0) {
			if (IsSeparatorOrNull(linkStr[curLen])) {
			    if (curLen) {
				Tcl_SetObjLength(retVal, curLen);
			    } else {
				Tcl_SetObjLength(retVal, 1);
			    }
			    break;







|














|
>


>
|







315
316
317
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) {
				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). In the case of
		     * zipfs, make sure not to go beyond the zipfs volume.
		     */

		    int minLen = zipVolumeLen ? zipVolumeLen - 1 : 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
	    retVal = Tcl_DuplicateObj(pathPtr);
	    Tcl_IncrRefCount(retVal);
	}
    }

    /*
     * Ensure a windows drive like C:/ has a trailing separator.

     */

    if (tclPlatform == TCL_PLATFORM_WINDOWS) {

	size_t len;
	const char *path = TclGetStringFromObj(retVal, &len);





	if (len == 2 && path[0] != 0 && path[1] == ':') {




	    if (Tcl_IsShared(retVal)) {
		TclDecrRefCount(retVal);
		retVal = Tcl_DuplicateObj(retVal);
		Tcl_IncrRefCount(retVal);
	    }
	    Tcl_AppendToObj(retVal, "/", 1);
	}







>

<
|
>
|

>
>
>
|
>
|
>
>
>
>







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 (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;
	    }
	} 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
 *----------------------------------------------------------------------
 */

Tcl_PathType
TclFSGetPathType(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem **filesystemPtrPtr,
    int *driveNameLengthPtr)
{
    FsPath *fsPathPtr;

    if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) {
	return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr,
		NULL);
    }







|







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,
    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
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclPathPart(
    Tcl_Interp *interp,		/* Used for error reporting */
    Tcl_Obj *pathPtr,		/* Path to take dirname of */
    Tcl_PathPart portion)	/* Requested portion of name */
{
    if (TclHasIntRep(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;
		const char *rest = TclGetStringFromObj(fsPathPtr->normPathPtr, &numBytes);

		if (strchr(rest, '/') != NULL) {
		    goto standardPath;
		}
		/*
		 * If the joined-on bit is empty, then [file dirname] is







|



|













|







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_UNUSED(Tcl_Interp *),	/* Used for error reporting */
    Tcl_Obj *pathPtr,		/* Path to take dirname of */
    Tcl_PathPart portion)	/* Requested portion of name */
{
    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.
		 */

		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
		/*
		 * 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;
		const char *rest = TclGetStringFromObj(fsPathPtr->normPathPtr, &numBytes);

		if (strchr(rest, '/') != NULL) {
		    goto standardPath;
		}
		/*
		 * If the joined-on bit is empty, then [file tail] is







|







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.
		 */

		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
		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;

		fileName = TclGetStringFromObj(fsPathPtr->normPathPtr,
			&length);
		extension = TclGetExtension(fileName);
		if (extension == NULL) {
		    /*
		     * There is no extension so the root is the same as the







|







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;
		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
	    /* Relative path */
	    goto standardPath;
	} else {
	    /* Absolute path */
	    goto standardPath;
	}
    } else {
	int 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;
	    const char *fileName, *extension;

	    fileName = TclGetStringFromObj(pathPtr, &length);
	    extension = TclGetExtension(fileName);
	    if (extension == NULL) {
		Tcl_IncrRefCount(pathPtr);
		return pathPtr;







|







|







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 {
	Tcl_Size splitElements;
	Tcl_Obj *splitPtr, *resultPtr;

    standardPath:
	resultPtr = NULL;
	if (portion == TCL_PATH_EXTENSION) {
	    return GetExtension(pathPtr);
	} else if (portion == TCL_PATH_ROOT) {
	    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
720
	 * 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) ||
		    (Tcl_FSGetPathType(pathPtr) == TCL_PATH_RELATIVE))) {







<
<

<
<
<
<
<
<
<
<
|







721
722
723
724
725
726
727


728








729
730
731
732
733
734
735
736
	 * 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 (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) ||
		    (Tcl_FSGetPathType(pathPtr) == TCL_PATH_RELATIVE))) {
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_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_Obj *res;
    int objc;
    Tcl_Obj **objv;

    if (Tcl_ListObjLength(NULL, listObj, &objc) != TCL_OK) {
	return NULL;
    }

    elements = ((elements >= 0) && (elements <= objc)) ? elements : objc;
    Tcl_ListObjGetElements(NULL, listObj, &objc, &objv);
    res = TclJoinPath(elements, objv, 0);
    return res;
}

Tcl_Obj *
TclJoinPath(
    int elements,		/* Number of elements to use (-1 = all) */
    Tcl_Obj * const objv[],	/* Path elements to join */
    int forceRelative)		/* If non-zero, assume all more paths are
				 * relative (e. g. simple normalization) */
{
    Tcl_Obj *res = NULL;
    int i;
    const Tcl_Filesystem *fsPtr = NULL;

    assert ( elements >= 0 );

    if (elements == 0) {

	return Tcl_NewObj();
    }

    assert ( elements > 0 );

    if (elements == 2) {
	Tcl_Obj *elt = objv[0];
	Tcl_ObjIntRep *eltIr = TclFetchIntRep(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







|


|


|




|






|


|


|


<
<

>
|






|







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. */
    Tcl_Size elements)		/* Number of elements to use (-1 = all) */
{
    Tcl_Obj *res;
    Tcl_Size objc;
    Tcl_Obj **objv;

    if (TclListObjLength(NULL, listObj, &objc) != TCL_OK) {
	return NULL;
    }

    elements = ((elements >= 0) && (elements <= objc)) ? elements : objc;
    TclListObjGetElements(NULL, listObj, &objc, &objv);
    res = TclJoinPath(elements, objv, 0);
    return res;
}

Tcl_Obj *
TclJoinPath(
    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) */
{
    Tcl_Obj *res = NULL;
    Tcl_Size i;
    const Tcl_Filesystem *fsPtr = NULL;



    if (elements == 0) {
	TclNewObj(res);
	return res;
    }

    assert ( elements > 0 );

    if (elements == 2) {
	Tcl_Obj *elt = objv[0];
	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
	    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;

		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
		 * 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).
		 */








|













|







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;
		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
		 * 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
	    }
	}
    }

    assert ( res == NULL );

    for (i = 0; i < elements; i++) {
	int driveNameLength;
	size_t strEltLen, length;
	Tcl_PathType type;
	char *strElt, *ptr;
	Tcl_Obj *driveName = NULL;
	Tcl_Obj *elt = objv[i];

	strElt = TclGetStringFromObj(elt, &strEltLen);
	driveNameLength = 0;







|
|







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++) {
	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
1059
1060

    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') {
	    continue;
	}







|
<
<
<
<
<
<
<
<
<
<
|







1050
1051
1052
1053
1054
1055
1056
1057










1058
1059
1060
1061
1062
1063
1064
1065

    noQuickReturn:
	if (res == NULL) {
	    TclNewObj(res);
	}
	ptr = TclGetStringFromObj(res, &length);

        /*










         * 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') {
	    continue;
	}
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
     * 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 (TclFSEpochOk(PATHOBJ(pathPtr)->filesystemEpoch)) {
	    return TCL_OK;
	}

	TclGetString(pathPtr);
	Tcl_StoreIntRep(pathPtr, &fsPathType, NULL);
    }

    return SetFsPathFromAny(interp, pathPtr);
}

/*
 * Helper function for normalization.







|





|







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 (TclHasInternalRep(pathPtr, &fsPathType)) {
	if (TclFSEpochOk(PATHOBJ(pathPtr)->filesystemEpoch)) {
	    return TCL_OK;
	}

	TclGetString(pathPtr);
	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

/*
 * 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
FindSplitPos(
    const char *path,
    int separator)
{
    int count = 0;
    switch (tclPlatform) {
    case TCL_PLATFORM_UNIX:







|







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 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
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclNewFSPathObj(
    Tcl_Obj *dirPtr,
    const char *addStrRep,
    size_t len)
{
    FsPath *fsPathPtr;
    Tcl_Obj *pathPtr;
    const char *p;
    int state = 0, count = 0;




    /* [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.
     */







|






>
>
>
|















<
<
<
<
<
<
<







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,
    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.
     * 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.
     */








    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

    /*
     * 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--) {
	switch (state) {
	case 0:		/* So far only "." since last dirsep or start */
	    switch (*p) {
	    case '.':
		count = 1;
		break;
	    case '/':







|







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 > 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
static Tcl_Obj *
AppendPath(
    Tcl_Obj *head,
    Tcl_Obj *tail)
{
    const char *bytes;
    Tcl_Obj *copy = Tcl_DuplicateObj(head);
    size_t 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
     * 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);







|






|







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);
    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
     * 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

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;
    const char *tempStr;
    Tcl_ObjIntRep *irPtr = TclFetchIntRep(pathPtr, &fsPathType);

    if (irPtr) {
	FsPath *fsPathPtr = PATHOBJ(pathPtr);

	if (PATHFLAGS(pathPtr) != 0 && fsPathPtr->cwdPtr == cwdPtr) {
	    return fsPathPtr->normPathPtr;
	}







|

|







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. */
{
    Tcl_Size cwdLen, len;
    const char *tempStr;
    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
static int
MakePathFromNormalized(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *pathPtr)		/* The object to convert. */
{
    FsPath *fsPathPtr;

    if (TclHasIntRep(pathPtr, &fsPathType)) {
	return TCL_OK;
    }

    fsPathPtr = (FsPath *)Tcl_Alloc(sizeof(FsPath));

    /*
     * It's a pure normalized absolute path.







|







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 (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
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_FSNewNativePath(
    const Tcl_Filesystem *fromFilesystem,
    ClientData 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);
    fsPathPtr = (FsPath *)Tcl_Alloc(sizeof(FsPath));

    fsPathPtr->translatedPathPtr = NULL;

    Tcl_IncrRefCount(fsPathPtr->normPathPtr = Tcl_DuplicateObj(pathPtr));
    fsPathPtr->cwdPtr = NULL;
    fsPathPtr->nativePathPtr = clientData;







|

















|







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 *
Tcl_FSNewNativePath(
    const Tcl_Filesystem *fromFilesystem,
    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_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
	     * (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;

	    if (translatedCwdPtr == NULL) {
		return NULL;
	    }

	    retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1,
		    &srcFsPathPtr->normPathPtr);
	    Tcl_IncrRefCount(srcFsPathPtr->translatedPathPtr = retObj);
	    translatedCwdIrPtr = TclFetchIntRep(translatedCwdPtr, &fsPathType);
	    if (translatedCwdIrPtr) {
		srcFsPathPtr->filesystemEpoch
			= PATHOBJ(translatedCwdPtr)->filesystemEpoch;
	    } else {
		srcFsPathPtr->filesystemEpoch = 0;
	    }
	    Tcl_DecrRefCount(translatedCwdPtr);







|








|







1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
	     * (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_ObjInternalRep *translatedCwdIrPtr;

	    if (translatedCwdPtr == NULL) {
		return NULL;
	    }

	    retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1,
		    &srcFsPathPtr->normPathPtr);
	    Tcl_IncrRefCount(srcFsPathPtr->translatedPathPtr = retObj);
	    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
Tcl_FSGetTranslatedStringPath(
    Tcl_Interp *interp,
    Tcl_Obj *pathPtr)
{
    Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(interp, pathPtr);

    if (transPtr != NULL) {
	size_t len;
	const char *orig = TclGetStringFromObj(transPtr, &len);
	char *result = (char *)Tcl_Alloc(len+1);

	memcpy(result, orig, len+1);
	TclDecrRefCount(transPtr);
	return result;
    }







|







1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
Tcl_FSGetTranslatedStringPath(
    Tcl_Interp *interp,
    Tcl_Obj *pathPtr)
{
    Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(interp, pathPtr);

    if (transPtr != NULL) {
	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
    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;
	int pathType;

	pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr);
	dir = Tcl_FSGetNormalizedPath(interp, fsPathPtr->cwdPtr);
	if (dir == NULL) {
	    return NULL;
	}







|







1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
    if (PATHFLAGS(pathPtr) != 0) {
	/*
	 * This is a special path object which is the result of something like
	 * 'file join'
	 */

	Tcl_Obj *dir, *copy;
	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
    /*
     * Ensure cwd hasn't changed.
     */

    if (fsPathPtr->cwdPtr != NULL) {
	if (!TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) {
	    TclGetString(pathPtr);
	    Tcl_StoreIntRep(pathPtr, &fsPathType, NULL);
	    if (SetFsPathFromAny(interp, pathPtr) != TCL_OK) {
		return NULL;
	    }
	    fsPathPtr = PATHOBJ(pathPtr);
	} else if (fsPathPtr->normPathPtr == NULL) {
	    size_t cwdLen;
	    Tcl_Obj *copy;

	    copy = AppendPath(fsPathPtr->cwdPtr, pathPtr);

	    (void) TclGetStringFromObj(fsPathPtr->cwdPtr, &cwdLen);
	    cwdLen += (TclGetString(copy)[cwdLen] == '/');








|





|







1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
    /*
     * Ensure cwd hasn't changed.
     */

    if (fsPathPtr->cwdPtr != NULL) {
	if (!TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) {
	    TclGetString(pathPtr);
	    Tcl_StoreInternalRep(pathPtr, &fsPathType, NULL);
	    if (SetFsPathFromAny(interp, pathPtr) != TCL_OK) {
		return NULL;
	    }
	    fsPathPtr = PATHOBJ(pathPtr);
	} else if (fsPathPtr->normPathPtr == NULL) {
	    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
 *
 *	Tcl_FSCreateInternalRepProc if needed to produce the native
 *	handle, which is then stored in the internal representation of pathPtr.
 *
 *---------------------------------------------------------------------------
 */

ClientData
Tcl_FSGetInternalRep(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem *fsPtr)
{
    FsPath *srcFsPathPtr;

    if (Tcl_FSConvertToPathType(NULL, pathPtr) != TCL_OK) {







|







1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
 *
 *	Tcl_FSCreateInternalRepProc if needed to produce the native
 *	handle, which is then stored in the internal representation of pathPtr.
 *
 *---------------------------------------------------------------------------
 */

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
int
TclFSEnsureEpochOk(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem **fsPtrPtr)
{
    FsPath *srcFsPathPtr;

    if (!TclHasIntRep(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);
	if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) {
	    return TCL_ERROR;
	}
	srcFsPathPtr = PATHOBJ(pathPtr);
    }

    if (srcFsPathPtr->fsPtr != NULL) {







|













|







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
int
TclFSEnsureEpochOk(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem **fsPtrPtr)
{
    FsPath *srcFsPathPtr;

    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_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
 *---------------------------------------------------------------------------
 */

void
TclFSSetPathDetails(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem *fsPtr,
    ClientData clientData)
{
    FsPath *srcFsPathPtr;

    /*
     * Make sure pathPtr is of the correct type.
     */

    if (!TclHasIntRep(pathPtr, &fsPathType)) {
	if (SetFsPathFromAny(NULL, pathPtr) != TCL_OK) {
	    return;
	}
    }

    srcFsPathPtr = PATHOBJ(pathPtr);
    srcFsPathPtr->fsPtr = fsPtr;







|







|







2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
 *---------------------------------------------------------------------------
 */

void
TclFSSetPathDetails(
    Tcl_Obj *pathPtr,
    const Tcl_Filesystem *fsPtr,
    void *clientData)
{
    FsPath *srcFsPathPtr;

    /*
     * Make sure pathPtr is of the correct type.
     */

    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

int
Tcl_FSEqualPaths(
    Tcl_Obj *firstPtr,
    Tcl_Obj *secondPtr)
{
    const char *firstStr, *secondStr;
    size_t firstLen, secondLen;
    int tempErrno;

    if (firstPtr == secondPtr) {
	return 1;
    }

    if (firstPtr == NULL || secondPtr == NULL) {







|







2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152

int
Tcl_FSEqualPaths(
    Tcl_Obj *firstPtr,
    Tcl_Obj *secondPtr)
{
    const char *firstStr, *secondStr;
    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
 *---------------------------------------------------------------------------
 *
 * 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_Obj *pathPtr)		/* The object to convert. */
{
    size_t len;
    FsPath *fsPathPtr;
    Tcl_Obj *transPtr;
    const char *name;

    if (TclHasIntRep(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);

    /*
     * 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);
    }

    /*
     * 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) {


        transPtr = Tcl_DuplicateObj(pathPtr);
        fsPathPtr->filesystemEpoch = 0;
    } else {
        fsPathPtr->filesystemEpoch = TclFSEpoch();
    }
    Tcl_IncrRefCount(transPtr);
    fsPathPtr->translatedPathPtr = transPtr;
    fsPathPtr->normPathPtr = NULL;
    fsPathPtr->cwdPtr = NULL;
    fsPathPtr->nativePathPtr = NULL;
    fsPathPtr->fsPtr = NULL;







<
<
<
<











|


|


<

|

















|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<









>
>
|
|

|







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
 *---------------------------------------------------------------------------
 *
 * SetFsPathFromAny --
 *
 *	Attempt to convert the internal representation of pathPtr to
 *	fsPathType.
 *




 * Results:
 *	Standard Tcl error code.
 *
 * Side effects:
 *	The old representation may be freed, and new memory allocated.
 *
 *---------------------------------------------------------------------------
 */

static int
SetFsPathFromAny(
    TCL_UNUSED(Tcl_Interp *),	/* Used for error reporting if not NULL. */
    Tcl_Obj *pathPtr)		/* The object to convert. */
{
    Tcl_Size len;
    FsPath *fsPathPtr;
    Tcl_Obj *transPtr;


    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).
     */

    TclGetStringFromObj(pathPtr, &len); /* TODO: Is this needed? */


















































































































    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;
    } else {
	fsPathPtr->filesystemEpoch = TclFSEpoch();
    }
    Tcl_IncrRefCount(transPtr);
    fsPathPtr->translatedPathPtr = transPtr;
    fsPathPtr->normPathPtr = NULL;
    fsPathPtr->cwdPtr = NULL;
    fsPathPtr->nativePathPtr = NULL;
    fsPathPtr->fsPtr = NULL;
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
 */

static void
UpdateStringOfFsPath(
    Tcl_Obj *pathPtr)	/* path obj with string rep to update. */
{
    FsPath *fsPathPtr = PATHOBJ(pathPtr);
    size_t cwdLen;
    Tcl_Obj *copy;

    if (PATHFLAGS(pathPtr) == 0 || fsPathPtr->cwdPtr == NULL) {

	Tcl_Panic("Called UpdateStringOfFsPath with invalid object");


    }

    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);
    TclDecrRefCount(copy);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclNativePathInFilesystem --







|



>
|
>
>
|
|
|
>
>








|







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
 */

static void
UpdateStringOfFsPath(
    Tcl_Obj *pathPtr)	/* path obj with string rep to update. */
{
    FsPath *fsPathPtr = PATHOBJ(pathPtr);
    Tcl_Size cwdLen;
    Tcl_Obj *copy;

    if (PATHFLAGS(pathPtr) == 0 || fsPathPtr->cwdPtr == NULL) {
	if (fsPathPtr->translatedPathPtr == NULL) {
	    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;
    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
 *
 *---------------------------------------------------------------------------
 */

int
TclNativePathInFilesystem(
    Tcl_Obj *pathPtr,
    TCL_UNUSED(ClientData *))
{
    /*
     * 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 (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;

	(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;
}





















































































































































































































































/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|








|


















|

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








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
 *
 *---------------------------------------------------------------------------
 */

int
TclNativePathInFilesystem(
    Tcl_Obj *pathPtr,
    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 (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.
	 */

	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", (void *)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",
                        (void *)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);
}

/*
 *----------------------------------------------------------------------
 *
 * 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_Size split;
    Tcl_DString resolvedPath;

    path = TclGetStringFromObj(pathObj, &len);
    if (path[0] != '~') {
	return pathObj;
    }

    /*
     * We have multiple cases '~/foo/bar...', '~user/foo/bar...', etc.
     * split becomes value 1 for '~/...' as well as for '~'. Note on
     * Windows FindSplitPos will implicitly check for '\' as separator
     * in addition to what is passed.
     */
    split = FindSplitPos(path, '/');

    if (split == 1) {
        /* No user name specified -> current user */
	if (MakeTildeRelativePath(interp, NULL, path[1] ? 2 + path : NULL,
		&resolvedPath) != TCL_OK) {
	    return NULL;
	}
    } else {
        /* User name specified - ~user */
        const char *expandedUser;
        Tcl_DString userName;

        Tcl_DStringInit(&userName);
        Tcl_DStringAppend(&userName, path+1, split-1);
        expandedUser = Tcl_DStringValue(&userName);

	/* path[split] is / or \0 */
	if (MakeTildeRelativePath(interp, expandedUser,
		path[split] ? &path[split+1] : NULL,
		&resolvedPath) != TCL_OK) {
	    Tcl_DStringFree(&userName);
	    return NULL;
	}
	Tcl_DStringFree(&userName);
    }
    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
/*
 * 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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|







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 © 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
		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);
	    }
	    return NULL;
	}
	*releasePtr = 1;
	if (writing) {
	    /*
	     * Be sure to flush output to the file, so that anything written







|







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", (void *)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
	*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);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DetachPids --







|







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", (void *)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
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DetachPids(
    int 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_MutexLock(&pipeMutex);
    for (i = 0; i < numPids; i++) {
	detPtr = (Detached *)Tcl_Alloc(sizeof(Detached));
	detPtr->pid = pidPtr[i];
	detPtr->nextPtr = detList;
	detList = detPtr;







|




|







175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DetachPids(
    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;
    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
 *
 *----------------------------------------------------------------------
 */

int
TclCleanupChildren(
    Tcl_Interp *interp,		/* Used for error messages. */
    int 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;
    TclProcessWaitStatus waitStatus;
    int code;
    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;







|






|

|







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. */
    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 code, abnormalExit, anyErrorInfo;
    TclProcessWaitStatus waitStatus;
    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

	if (interp != NULL) {
	    int count;
	    Tcl_Obj *objPtr;

	    Tcl_Seek(errorChan, 0, SEEK_SET);
	    TclNewObj(objPtr);
	    count = Tcl_ReadChars(errorChan, objPtr, -1, 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)));







|







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, 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
 *	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
 *	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
TclCreatePipeline(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    int 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.
				 * 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
				 * *pidPtr right now. */
    int 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







|
















|


|
















|















|

|







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
 *	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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclCreatePipeline(
    Tcl_Interp *interp,		/* Interpreter to use for error reporting. */
    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
				 * 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. */
    Tcl_Size numPids;		/* Actual number of processes that exist at
				 * *pidPtr right now. */
    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
				 * 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;

    Tcl_DString execBuffer;
    TclFile pipeIn;
    TclFile curInFile, curOutFile, curErrFile;
    Tcl_Channel channel;

    if (inPipePtr != NULL) {
	*inPipePtr = NULL;







|
>







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, 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

    /*
     * 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
     * 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;







|







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 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
		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);
		    goto error;
		}
	    }
	    lastBar = i;
	    cmdCount++;
	    needCmd = 1;
	    break;







|







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", (void *)NULL);
		    goto error;
		}
	    }
	    lastBar = i;
	    cmdCount++;
	    needCmd = 1;
	    break;
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
		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);
			goto error;
		    }
		    skip = 2;
		}
	    } else {
		nextArg = ((i + 1) == argc) ? NULL : argv[i + 1];
		inputLiteral = NULL;







|







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", (void *)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
		 */

		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);
		    goto error;
		}
		errorFile = outputFile;
		errorToOutput = 2;
		skip = 1;
	    } else {
		nextArg = ((i + 1) == argc) ? NULL : argv[i + 1];







|







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", (void *)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
	/*
	 * 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);
	goto error;
    }

    if (inputFile == NULL) {
	if (inputLiteral != NULL) {
	    /*
	     * The input for the first process is immediate data coming from







|







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",
		(void *)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
    }
    if ((errFilePtr != NULL) && (*errFilePtr != NULL)) {
	TclpCloseFile(*errFilePtr);
	*errFilePtr = NULL;
    }
    if (pidPtr != NULL) {
	for (i = 0; i < numPids; i++) {
	    if (pidPtr[i] != (Tcl_Pid) -1) {
		Tcl_DetachPids(1, &pidPtr[i]);
	    }
	}
	Tcl_Free(pidPtr);
    }
    numPids = -1;
    goto cleanup;







|







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) {
		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
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_OpenCommandChannel(
    Tcl_Interp *interp,		/* Interpreter for error reporting. Can NOT be
				 * NULL. */
    int 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_Channel channel;

    inPipe = outPipe = errFile = NULL;

    inPipePtr = (flags & TCL_STDIN) ? &inPipe : NULL;
    outPipePtr = (flags & TCL_STDOUT) ? &outPipe : NULL;
    errFilePtr = (flags & TCL_STDERR) ? &errFile : NULL;







|






|
|







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. */
    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;
    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

    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);
	    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);
	    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);
	goto error;
    }
    return channel;

  error:
    if (numPids > 0) {
	Tcl_DetachPids(numPids, pidPtr);
	Tcl_Free(pidPtr);
    }
    if (inPipe != NULL) {
	TclpCloseFile(inPipe);
    }
    if (outPipe != NULL) {







|







|










|





|







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", (void *)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", (void *)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", (void *)NULL);
	goto error;
    }
    return channel;

  error:
    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
/*
 * 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 <[email protected]>
 *
 * 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.






|
|







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 © 1996 Sun Microsystems, Inc.
 * Copyright © 2006 Andreas Kupries <[email protected]>
 *
 * 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
    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];
} PkgName;

typedef struct PkgFiles {
    PkgName *names;		/* Package names being initialized. Must be
				 * first field. */
    Tcl_HashTable table;	/* Table which contains files for each
				 * package. */







|







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[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
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);

/*
 * Helper macros.
 */

#define DupBlock(v,s,len) \
    ((v) = (char *)Tcl_Alloc(len), memcpy((v),(s),(len)))







|
|
|
|
|
|
|
|
|







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(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
	    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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PkgRequire / Tcl_PkgRequireEx / Tcl_PkgRequireProc --







|







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", (void *)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
 *	invoked to provide the package.
 *
 *----------------------------------------------------------------------
 */

static void
PkgFilesCleanupProc(
    ClientData clientData,
    TCL_UNUSED(Tcl_Interp *))
{
    PkgFiles *pkgFiles = (PkgFiles *) clientData;
    Tcl_HashSearch search;
    Tcl_HashEntry *entry;

    while (pkgFiles->names) {







|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
 *	invoked to provide the package.
 *
 *----------------------------------------------------------------------
 */

static void
PkgFilesCleanupProc(
    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
	 * 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);
	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));
	    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_IncrRefCount(ov);
	if (Tcl_PkgRequireProc(interp, name, 1, &ov, clientDataPtr) == TCL_OK) {
	    result = Tcl_GetString(Tcl_GetObjResult(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
				 * 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,
    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[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    const char *name = (const char *)data[0];
    int reqc = PTR2INT(data[1]);
    Tcl_Obj **reqv = (Tcl_Obj **)data[2];
    int code = CheckAllRequirements(interp, reqc, reqv);
    Require *reqPtr;

    if (code != TCL_OK) {
	return code;
    }







|









|









|



|












|















|














|




|







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", (void *)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_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, (void *)NULL);
	}
	Tcl_IncrRefCount(ov);
	if (Tcl_PkgRequireProc(interp, name, 1, &ov, clientDataPtr) == TCL_OK) {
	    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. */
    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(
    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(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    const char *name = (const char *)data[0];
    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
		PkgRequireCoreFinal, reqPtr, INT2PTR(reqc), reqv, NULL);
    }
    return TCL_OK;
}

static int
PkgRequireCoreStep1(
    ClientData data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    Tcl_DString command;
    char *script;
    Require *reqPtr = (Require *)data[0];
    int reqc = 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.
     */







|






|







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(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    Tcl_DString command;
    char *script;
    Require *reqPtr = (Require *)data[0];
    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.
     */
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
	    TCL_EVAL_GLOBAL);
    Tcl_DStringFree(&command);
    return TCL_OK;
}

static int
PkgRequireCoreStep2(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    Require *reqPtr = (Require *)data[0];
    int reqc = 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);
	result = TCL_ERROR;
    }
    if (result == TCL_ERROR) {
	Tcl_AddErrorInfo(interp,
		"\n    (\"package unknown\" script)");
	return result;
    }







|




|






|







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
	    TCL_EVAL_GLOBAL);
    Tcl_DStringFree(&command);
    return TCL_OK;
}

static int
PkgRequireCoreStep2(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Require *reqPtr = (Require *)data[0];
    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", (void *)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
	    SelectPackage, reqPtr, INT2PTR(reqc), reqv,
	    (void *)PkgRequireCoreFinal);
    return TCL_OK;
}

static int
PkgRequireCoreFinal(
    ClientData data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    Require *reqPtr = (Require *)data[0];
    int reqc = 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);
	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);
	    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[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    Tcl_Free(data[0]);
    return result;
}

static int
SelectPackage(
    ClientData 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]);
    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);
	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







|




|








|




















|
















|









|








|
















|







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
	    SelectPackage, reqPtr, INT2PTR(reqc), reqv,
	    (void *)PkgRequireCoreFinal);
    return TCL_OK;
}

static int
PkgRequireCoreFinal(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int))
{
    Require *reqPtr = (Require *)data[0];
    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", (void *)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",
		    (void *)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(
    void *data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    Tcl_Free(data[0]);
    return result;
}

static int
SelectPackage(
    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 = (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", (void *)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

	pkgFiles = (PkgFiles *)TclInitPkgFiles(interp);

	/*
	 * Push "ifneeded" package name in "tclPkgFiles" assocdata.
	 */

	pkgName = (PkgName *)Tcl_Alloc(sizeof(PkgName) + 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[],
    Tcl_Interp *interp,
    int result)
{
    Require *reqPtr = (Require *)data[0];
    int reqc = 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
     */







|


















|




|







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

	pkgFiles = (PkgFiles *)TclInitPkgFiles(interp);

	/*
	 * Push "ifneeded" package name in "tclPkgFiles" assocdata.
	 */

	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(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Require *reqPtr = (Require *)data[0];
    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
	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);
	} else {
	    char *pvi, *vi;

	    if (TCL_OK != CheckVersionAndConvert(interp,
		    Tcl_GetString(reqPtr->pkgPtr->version), &pvi, NULL)) {
		result = TCL_ERROR;
	    } else if (CheckVersionAndConvert(interp,







|







872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
	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",
		    (void *)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
		    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);
		}
	    }
	}
    } 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);
	TclDecrRefCount(codePtr);
	result = TCL_ERROR;
    }

    if (result == TCL_ERROR) {
	Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
		"\n    (\"package ifneeded %s %s\" script)",







|











|







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
		    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", (void *)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", (void *)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
	     */

	    const char *foundVersion = Tcl_PkgRequireEx(interp, name, version,
		    exact, clientDataPtr);

	    if (foundVersion == NULL) {
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name,
			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);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_PackageObjCmd --







|












|







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
	     */

	    const char *foundVersion = Tcl_PkgRequireEx(interp, name, version,
		    exact, clientDataPtr);

	    if (foundVersion == NULL) {
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "PACKAGE", name,
			(void *)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, (void *)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
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */
int
Tcl_PackageObjCmd(
    ClientData 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_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
    };
    Interp *iPtr = (Interp *) interp;
    int optionIndex, exact, i, newobjc, satisfies;

    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) {
    case PKG_FILES: {
	PkgFiles *pkgFiles;

	if (objc != 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "package");
	    return TCL_ERROR;
	}







|









|













|

|
>



















|







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
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */
int
Tcl_PackageObjCmd(
    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(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 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 (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
		Tcl_Free(availPtr);
	    }
	    Tcl_Free(pkgPtr);
	}
	break;
    }
    case PKG_IFNEEDED: {
	size_t length;
	int res;
	char *argv3i, *avi;

	if ((objc != 4) && (objc != 5)) {
	    Tcl_WrongNumArgs(interp, 2, objv, "package version ?script?");
	    return TCL_ERROR;
	}







|







1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
		Tcl_Free(availPtr);
	    }
	    Tcl_Free(pkgPtr);
	}
	break;
    }
    case PKG_IFNEEDED: {
	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
	    }

	    /*
	     * Create a new-style requirement for the exact version.
	     */

	    ov = Tcl_NewStringObj(version, -1);
	    Tcl_AppendStringsToObj(ov, "-", version, 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);

	    Tcl_NRAddCallback(interp,
		    TclNRPackageObjCmdCleanup, objv[3], objvListPtr, NULL,NULL);
	    Tcl_NRAddCallback(interp,
		    PkgRequireCore, (void *) argv3, INT2PTR(newobjc),
		    newObjvPtr, NULL);
	    return TCL_OK;







|







|







1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
	    }

	    /*
	     * Create a new-style requirement for the exact version.
	     */

	    ov = Tcl_NewStringObj(version, -1);
	    Tcl_AppendStringsToObj(ov, "-", version, (void *)NULL);
	    version = NULL;
	    argv3 = TclGetString(objv[3]);
	    Tcl_IncrRefCount(objv[3]);

	    objvListPtr = Tcl_NewListObj(0, NULL);
	    Tcl_IncrRefCount(objvListPtr);
	    Tcl_ListObjAppendElement(interp, objvListPtr, ov);
	    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
		 * 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);
	    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;

	if (objc == 2) {
	    if (iPtr->packageUnknown != NULL) {
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj(iPtr->packageUnknown, -1));
	    }
	} else if (objc == 3) {







|









|







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
		 * Tcl_Obj structures may have come from another interpreter,
		 * so duplicate them.
		 */

		Tcl_ListObjAppendElement(interp, objvListPtr,
			Tcl_DuplicateObj(newobjv[i]));
	    }
	    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: {
	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
	Tcl_Panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
    }
    return TCL_OK;
}

static int
TclNRPackageObjCmdCleanup(
    ClientData data[],
    TCL_UNUSED(Tcl_Interp *),
    int result)
{
    TclDecrRefCount((Tcl_Obj *) data[0]);
    TclDecrRefCount((Tcl_Obj *) data[1]);
    return result;
}







|







1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
	Tcl_Panic("Tcl_PackageObjCmd: bad option index to pkgOptions");
    }
    return TCL_OK;
}

static int
TclNRPackageObjCmdCleanup(
    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
    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
     */
    char *ibuf = (char *)Tcl_Alloc(4 + 4*strlen(string));
    char *ip = ibuf;

    /*
     * Basic rules
     * (1) First character has to be a digit.







|







1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
    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 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

    if (!isdigit(UCHAR(*p))) {				/* INTL: digit */
	goto error;
    }

    *ip++ = *p;

    for (prevChar = *p, p++; *p != 0; 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;







|







1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709

    if (!isdigit(UCHAR(*p))) {				/* INTL: digit */
	goto error;
    }

    *ip++ = *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
	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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * CompareVersions --







|







1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
	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", (void *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * CompareVersions --
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794

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. */
{
    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







|







1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795

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 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
     * Syntax of requirement = version
     *			     = version-version
     *			     = version-
     */

    char *dash = NULL, *buf;

    dash = (char *)strchr(string, '-');
    if (dash == NULL) {
	/*
	 * 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);
	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







|


|












|







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
     * Syntax of requirement = version
     *			     = version-version
     *			     = version-
     */

    char *dash = NULL, *buf;

    dash = strchr(string, '+') ? NULL : (char *)strchr(string, '-');
    if (dash == NULL) {
	/*
	 * '+' 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", (void *)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
    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;

    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));







|







2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
    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;
    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
	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
     * a bit.
     */

    CheckVersionAndConvert(NULL, buf, &min, NULL);
    CheckVersionAndConvert(NULL, dash, &max, NULL);

    if (CompareVersions(min, max, NULL) == 0) {







|







2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
	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 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
/*
 * tclPkgConfig.c --
 *
 *	This file contains the configuration information to embed into the tcl
 *	binary library.
 *
 * Copyright (c) 2002 Andreas Kupries <[email protected]>
 *
 * 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:




|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * tclPkgConfig.c --
 *
 *	This file contains the configuration information to embed into the tcl
 *	library.
 *
 * Copyright © 2002 Andreas Kupries <[email protected]>
 *
 * 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:
105
106
107
108
109
110
111

112
113

114
115
116
117
118
119
120
    /* 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},

    {"dllfile,runtime",		CFG_RUNTIME_DLLFILE},
    {"zipfile,runtime",		CFG_RUNTIME_ZIPFILE},


    /* 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},







>

<
>







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},

#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
	typedef wchar_t TCHAR;
#   else
	typedef char TCHAR;
#   endif
#   define _TCHAR_DEFINED
#endif








/* !BEGIN!: Do not edit below this line. */


#ifdef __cplusplus
extern "C" {
#endif

/*
 * Exported function declarations:
 */












#ifdef MAC_OSX_TCL /* MACOSX */












































































/* Slot 0 is reserved */
/* 1 */
EXTERN int		Tcl_MacOSXOpenVersionedBundleResources(
				Tcl_Interp *interp, const char *bundleName,
				const char *bundleVersion,
				int hasResourceFile, size_t maxPathLen,
				char *libraryPath);
#endif /* MACOSX */





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 */
} 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 */



#endif /* MACOSX */

#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */



#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











#if defined(USE_TCL_STUBS) && defined(_WIN32) && !defined(TCL_NO_DEPRECATED)




#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 /* _TCLPLATDECLS */







>
>
>
>
>
>
>
|
>









>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|

|
>
>
>
>





<

|
>
|














<



>
>
>
|




>
>









>
>
>
>
>
>
>
>
>
>
|
>
>
>
>




>



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
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

#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, Tcl_Size maxPathLen,
				char *libraryPath);
/* 2 */
EXTERN void		Tcl_MacOSXNotifierAddRunLoopMode(
				const void *runLoopMode);
/* 3 */
EXTERN void		Tcl_WinConvertError(unsigned errCode);

typedef struct TclPlatStubs {
    int magic;
    void *hooks;


    void (*reserved0)(void);
    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:
 */


/* Slot 0 is reserved */
#define Tcl_MacOSXOpenVersionedBundleResources \
	(tclPlatStubsPtr->tcl_MacOSXOpenVersionedBundleResources) /* 1 */
#define Tcl_MacOSXNotifierAddRunLoopMode \
	(tclPlatStubsPtr->tcl_MacOSXNotifierAddRunLoopMode) /* 2 */
#define Tcl_WinConvertError \
	(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(__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
/*
 * 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.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|
|







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 © 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
#endif
#ifdef EALIGN
    case EALIGN: return "EALIGN";
#endif
#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY))
    case EALREADY: return "EALREADY";
#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 ECHILD
    case ECHILD: return "ECHILD";
#endif
#ifdef ECHRNG
    case ECHRNG: return "ECHRNG";
#endif
#ifdef ECOMM







>
>
>












<
<
<


















>
>
>
>
>
>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79



80
81
82
83
84
85
86
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 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
#endif
#ifdef EDUPPKG
    case EDUPPKG: return "EDUPPKG";
#endif
#ifdef EEXIST
    case EEXIST: return "EEXIST";
#endif



#ifdef EFAULT
    case EFAULT: return "EFAULT";
#endif
#ifdef EFBIG
    case EFBIG: return "EFBIG";
#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 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
    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 ELIBACC
    case ELIBACC: return "ELIBACC";
#endif
#ifdef ELIBBAD
    case ELIBBAD: return "ELIBBAD";
#endif
#ifdef ELIBEXEC







>
>
>






>
>
>












>
>
>
>
>
>


















|


<
<
<












>
>
>







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
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 EISNAM
    case EISNAM: return "EISNAM";
#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
#endif
#ifdef ELNRNG
    case ELNRNG: return "ELNRNG";
#endif
#if defined(ELOOP) && (!defined(ENOENT) || (ELOOP != ENOENT))
    case ELOOP: return "ELOOP";
#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 ENOANO
    case ENOANO: return "ENOANO";
#endif
#if defined(ENOBUFS) && (!defined(ENOSR) || (ENOBUFS != ENOSR))
    case ENOBUFS: return "ENOBUFS";
#endif
#ifdef ENOCSI







>
>
>


















<
<
<












>
>
>







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
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 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
#endif
#ifdef ENOLINK
    case ENOLINK: return "ENOLINK";
#endif
#ifdef ENOMEM
    case ENOMEM: return "ENOMEM";
#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 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))







>
>
>












>
>
>







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
#endif
#ifdef ENOTTY
    case ENOTTY: return "ENOTTY";
#endif
#ifdef ENOTUNIQ
    case ENOTUNIQ: return "ENOTUNIQ";
#endif



#ifdef ENXIO
    case ENXIO: return "ENXIO";
#endif
#if defined(EOPNOTSUPP) &&  (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP))
    case EOPNOTSUPP: return "EOPNOTSUPP";
#endif
#ifdef EOTHER







>
>
>







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
#endif
#ifdef EREMOTEIO
    case EREMOTEIO: return "EREMOTEIO";
#endif
#ifdef EREMOTERELEASE
    case EREMOTERELEASE: return "EREMOTERELEASE";
#endif



#ifdef EROFS
    case EROFS: return "EROFS";
#endif
#ifdef ERPCMISMATCH
    case ERPCMISMATCH: return "ERPCMISMATCH";
#endif
#ifdef ERREMOTE







>
>
>







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
#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";
#endif
#if defined(EALREADY) && (!defined(EBUSY) || (EALREADY != EBUSY))
    case EALREADY: return "operation already in progress";
#endif



#ifdef EBADE
    case EBADE: return "bad exchange descriptor";
#endif
#ifdef EBADF
    case EBADF: return "bad file number";
#endif
#ifdef EBADFD
    case EBADFD: return "file descriptor in bad state";
#endif
#ifdef EBADMSG
    case EBADMSG: return "not a data message";
#endif
#ifdef ECANCELED
    case ECANCELED: return "operation canceled";
#endif
#ifdef EBADR
    case EBADR: return "bad request descriptor";
#endif
#ifdef EBADRPC
    case EBADRPC: return "RPC structure is bad";
#endif
#ifdef EBADRQC
    case EBADRQC: return "bad 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";
#endif






#ifdef ECHILD
    case ECHILD: return "no children";
#endif
#ifdef ECHRNG
    case ECHRNG: return "channel number out of range";
#endif
#ifdef ECOMM
    case ECOMM: return "communication error on send";
#endif







|




>
>
>

|


|





|

<
<
<

|





|








|

>
>
>
>
>
>

|







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 "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 "invalid exchange";
#endif
#ifdef EBADF
    case EBADF: return "bad file descriptor";
#endif
#ifdef EBADFD
    case EBADFD: return "file descriptor in bad state";
#endif
#ifdef EBADMSG
    case EBADMSG: return "bad message";
#endif



#ifdef EBADR
    case EBADR: return "invalid request descriptor";
#endif
#ifdef EBADRPC
    case EBADRPC: return "RPC structure is bad";
#endif
#ifdef EBADRQC
    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 "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 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
#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";
#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";
#endif



#ifdef EFAULT
    case EFAULT: return "bad address in system call argument";
#endif
#ifdef EFBIG
    case EFBIG: return "file too large";
#endif



#ifdef EHOSTDOWN
    case EHOSTDOWN: return "host is down";
#endif
#ifdef EHOSTUNREACH
    case EHOSTUNREACH: return "host is unreachable";
#endif
#if defined(EIDRM) && (!defined(EINPROGRESS) || (EIDRM != EINPROGRESS))
    case EIDRM: return "identifier removed";
#endif
#ifdef EINIT
    case EINIT: return "initialization error";
#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";
#endif
#ifdef EISCONN
    case EISCONN: return "socket is already connected";
#endif
#ifdef EISDIR
    case EISDIR: return "illegal operation on a directory";
#endif
#ifdef EISNAME
    case EISNAM: return "is a name 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 ELIBACC
    case ELIBACC: return "cannot 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";
#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 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";
#endif



#ifdef ENOANO
    case ENOANO: return "anode table overflow";
#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







|











|

>
>
>

|




>
>
>




|







>
>
>
>
>
>










|


|


|

|
|
<
<
<













>
>
>

|









|










>
>
>


















<
<
<










|

>
>
>

|







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 "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 exists";
#endif
#ifdef EFAIL
    case EFAIL: return "cannot start operation";
#endif
#ifdef EFAULT
    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 "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 "input/output error";
#endif
#ifdef EISCONN
    case EISCONN: return "transport endpoint is already connected";
#endif
#ifdef EISDIR
    case EISDIR: return "is a directory";
#endif
#ifdef EISNAM
    case EISNAM: return "is a named type file";



#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 "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 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 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 "too many open files in system";
#endif
#ifdef ENMFILE
    case ENMFILE: return "no more files";
#endif
#ifdef ENOANO
    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
#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";



#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";



#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";
#endif
#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
    case ENOSTR: return "not a stream device";
#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";
#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 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";
#endif
#ifdef ENOTUNIQ
    case ENOTUNIQ: return "name not unique on network";
#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";
#endif
#ifdef EOWNERDEAD
    case EOWNERDEAD: return "owner died";
#endif
#ifdef EPERM
    case EPERM: return "not owner";
#endif
#if defined(EPFNOSUPPORT) && (!defined(ENOLCK) || (ENOLCK != EPFNOSUPPORT))
    case EPFNOSUPPORT: return "protocol family not supported";
#endif
#ifdef EPIPE
    case EPIPE: return "broken pipe";
#endif







|
>
>
>











|
>
>
>





|


|











|
<
<
<










>
>
>







|




>
>
>










|





|







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 "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 "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 streams resources";
#endif
#if defined(ENOSTR) && (!defined(ENOTTY) || (ENOTTY != ENOSTR))
    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 "transport endpoint is not connected";



#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 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 "value too large for defined data type";
#endif
#ifdef EOWNERDEAD
    case EOWNERDEAD: return "owner died";
#endif
#ifdef EPERM
    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
#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";
#endif
#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
    case EREFUSED: return "EREFUSED";
#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";
#endif
#ifdef EREMOTEIO
    case EREMOTEIO: return "remote i/o error";
#endif
#ifdef EREMOTERELEASE
    case EREMOTERELEASE: return "EREMOTERELEASE";



#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";
#endif
#ifdef ESOCKTNOSUPPORT
    case ESOCKTNOSUPPORT: return "socket type not supported";
#endif
#ifdef ESPIPE
    case ESPIPE: return "invalid 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";
#endif



#ifdef ESUCCESS
    case ESUCCESS: return "Error 0";
#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";
#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";
#endif
#ifdef EXFULL
    case EXFULL: return "message tables full";
#endif
    default:
#ifdef NO_STRERROR
	return "unknown POSIX error";
#else
	return strerror(err);
#endif







|


|








|


|


|
>
>
>











|





|








|

>
>
>

|











|

















|


|







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 "numerical result out of range";
#endif
#if defined(EREFUSED) && (!defined(ECONNREFUSED) || (EREFUSED != ECONNREFUSED))
    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 "object is remote";
#endif
#ifdef EREMOTEIO
    case EREMOTEIO: return "remote I/O error";
#endif
#ifdef 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 transport endpoint shutdown";
#endif
#ifdef ESOCKTNOSUPPORT
    case ESOCKTNOSUPPORT: return "socket type not supported";
#endif
#ifdef ESPIPE
    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 file handle";
#endif
#ifdef ESTRPIPE
    case ESTRPIPE: return "streams pipe error";
#endif
#ifdef ESUCCESS
    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 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 "invalid cross-device link";
#endif
#ifdef EXFULL
    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
/*
 * 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.
 *
 * 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. */
    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. */







|
|














|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * 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 © 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 {
    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. */
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 *	until at least the matching call to Tcl_Release.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_Preserve(
    ClientData 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.







|







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 *	until at least the matching call to Tcl_Release.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_Preserve(
    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
 *	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. */
{
    Reference *refPtr;
    size_t i;

    Tcl_MutexLock(&preserveMutex);
    for (i=0, refPtr=refArray ; i<inUse ; i++, refPtr++) {
	int mustFree;







|







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
 *	call to Tcl_Preserve is still in effect, the block of memory is freed.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_Release(
    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
 *	Ptr may be released by calling free().
 *
 *----------------------------------------------------------------------
 */

void
Tcl_EventuallyFree(
    ClientData 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"







|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
 *	Ptr may be released by calling free().
 *
 *----------------------------------------------------------------------
 */

void
Tcl_EventuallyFree(
    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
    /*
     * No reference for this block.  Free it now.
     */

    if (freeProc == TCL_DYNAMIC) {
	Tcl_Free(clientData);
    } else {
	freeProc((char *)clientData);
    }
}

/*
 *---------------------------------------------------------------------------
 *
 * TclHandleCreate --







|







288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
    /*
     * No reference for this block.  Free it now.
     */

    if (freeProc == TCL_DYNAMIC) {
	Tcl_Free(clientData);
    } else {
	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
/*
 * 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 <[email protected]>
 *
 * 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"






|
|
|
|







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 © 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 <[email protected]>
 *
 * 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
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;


/*
 * 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
				 * should panic instead. */

};

#define ProcSetIntRep(objPtr, procPtr)					\
    do {								\
	Tcl_ObjIntRep ir;						\
	(procPtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (procPtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &tclProcBodyType, &ir);		\
    } while (0)

#define ProcGetIntRep(objPtr, procPtr)					\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &tclProcBodyType);		\
	(procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL;		\
    } while (0)

/*
 * The [upvar]/[uplevel] level reference type. Uses the longValue 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
};

/*
 * 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 */

};

#define LambdaSetIntRep(objPtr, procPtr, nsObjPtr)			\
    do {								\
	Tcl_ObjIntRep ir;						\
	ir.twoPtrValue.ptr1 = (procPtr);				\
	ir.twoPtrValue.ptr2 = (nsObjPtr);				\
	Tcl_IncrRefCount((nsObjPtr));					\
	Tcl_StoreIntRep((objPtr), &lambdaType, &ir);			\
    } while (0)

#define LambdaGetIntRep(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;		\
    } while (0)


/*
 *----------------------------------------------------------------------







>












|

>


|

|



|


|

|
|




|








|
















|
>


|

|



|


|

|
|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
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
				 * should panic instead. */
    TCL_OBJTYPE_V0
};

#define ProcSetInternalRep(objPtr, procPtr)					\
    do {								\
	Tcl_ObjInternalRep ir;						\
	(procPtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (procPtr);				\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreInternalRep((objPtr), &tclProcBodyType, &ir);		\
    } while (0)

#define ProcGetInternalRep(objPtr, procPtr)					\
    do {								\
	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 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, TCL_OBJTYPE_V0
};

/*
 * 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 */
    TCL_OBJTYPE_V0
};

#define LambdaSetInternalRep(objPtr, procPtr, nsObjPtr)			\
    do {								\
	Tcl_ObjInternalRep ir;						\
	ir.twoPtrValue.ptr1 = (procPtr);				\
	ir.twoPtrValue.ptr2 = (nsObjPtr);				\
	Tcl_IncrRefCount((nsObjPtr));					\
	Tcl_StoreInternalRep((objPtr), &lambdaType, &ir);			\
    } while (0)

#define LambdaGetInternalRep(objPtr, procPtr, nsObjPtr)			\
    do {								\
	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)


/*
 *----------------------------------------------------------------------
144
145
146
147
148
149
150

151
152
153
154
155
156
157
158
159
160
161
162
 *
 * Side effects:
 *	A new procedure gets created.
 *
 *----------------------------------------------------------------------
 */


int
Tcl_ProcObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int 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;







>


|

|







147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
 *
 * Side effects:
 *	A new procedure gets created.
 *
 *----------------------------------------------------------------------
 */

#undef TclObjInterpProc
int
Tcl_ProcObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    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
    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);
	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);
	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);

    /*
     * 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.
     */







|






|
















|







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
    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", (void *)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", (void *)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, 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
		    && (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[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);







|







265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
		    && (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 = (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
     *	   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) {
	goto done;
    }

    procArgs = TclGetString(objv[2]);

    while (*procArgs == ' ') {
	procArgs++;
    }

    if ((procArgs[0] == 'a') && (strncmp(procArgs, "args", 4) == 0)) {
	size_t numBytes;

	procArgs +=4;
	while (*procArgs != '\0') {
	    if (*procArgs != ' ') {
		goto done;
	    }
	    procArgs++;







|










|







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
     *	   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 (TclHasInternalRep(objv[3], &tclProcBodyType)) {
	goto done;
    }

    procArgs = TclGetString(objv[2]);

    while (*procArgs == ' ') {
	procArgs++;
    }

    if ((procArgs[0] == 'a') && (strncmp(procArgs, "args", 4) == 0)) {
	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
    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;
    CompiledLocal *localPtr = NULL;
    Tcl_Obj **argArray;
    int precompiled = 0;

    ProcGetIntRep(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).
	 *







|


|

|







404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
    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;
    Tcl_Size i, numArgs;
    CompiledLocal *localPtr = NULL;
    Tcl_Obj **argArray;
    int precompiled = 0, result;

    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
	 * 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_Obj *sharedBodyPtr = bodyPtr;

	    bytes = TclGetStringFromObj(bodyPtr, &length);
	    bodyPtr = Tcl_NewStringObj(bytes, length);

	    /*
	     * TIP #280.







|







444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
	 * 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;
	    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
    /*
     * 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);
    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,
		    procPtr->numArgs));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
		    "BYTECODELIES", 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;
	size_t nameLength;
	Tcl_Obj **fieldValues;

	/*
	 * Now divide the specifier up into name and default.
	 */

	result = Tcl_ListObjGetElements(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);
	    goto procError;
	}
	if ((fieldCount == 0) || (fieldValues[0]->length == 0)) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "argument with no name", -1));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
		    "FORMALARGUMENTFORMAT", 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);
		    goto procError;
		}
	    } else if (*argnamei == ':' && *(argnamei+1) == ':') {
		Tcl_Obj *errorObj = Tcl_NewStringObj(
		    "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);
		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
	     * 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 "
			"inconsistent with precompiled body", procName, i));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
			"BYTECODELIES", NULL);
		goto procError;
	    }

	    /*
	     * Compare the default value if any.
	     */

	    if (localPtr->defValuePtr != NULL) {
		size_t tmpLength, valueLength;
		const char *tmpPtr = TclGetStringFromObj(localPtr->defValuePtr, &tmpLength);
		const char *value = TclGetStringFromObj(fieldValues[1], &valueLength);

		if ((valueLength != tmpLength)
		     || 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);
		    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);
	    if (procPtr->firstLocalPtr == NULL) {
		procPtr->firstLocalPtr = procPtr->lastLocalPtr = localPtr;
	    } else {
		procPtr->lastLocalPtr->nextPtr = localPtr;
		procPtr->lastLocalPtr = localPtr;
	    }
	    localPtr->nextPtr = NULL;







|







|
|


|










|
<






|











|


|



|


















|


|

|




|












|











|


|








|




|
<







|


















|







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
    /*
     * 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 = 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 %" TCL_SIZE_MODIFIER "d entries, "
		    "precompiled header expects %" TCL_SIZE_MODIFIER "d", procName, numArgs,
		    procPtr->numArgs));
	    Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
		    "BYTECODELIES", (void *)NULL);
	    goto procError;
	}
	localPtr = procPtr->firstLocalPtr;
    } else {
	procPtr->numArgs = numArgs;
	procPtr->numCompiledLocals = numArgs;
    }

    for (i = 0; i < numArgs; i++) {
	const char *argname, *argnamei, *argnamelast;
	Tcl_Size fieldCount, nameLength;

	Tcl_Obj **fieldValues;

	/*
	 * Now divide the specifier up into name and default.
	 */

	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", (void *)NULL);
	    goto procError;
	}
	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", (void *)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", (void *)NULL);
		    goto procError;
		}
	    } else if (argnamei[0] == ':' && argnamei[1] == ':') {
		Tcl_Obj *errorObj = Tcl_NewStringObj(
			"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", (void *)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 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 %" TCL_SIZE_MODIFIER "d is "
			"inconsistent with precompiled body", procName, i));
		Tcl_SetErrorCode(interp, "TCL", "OPERATION", "PROC",
			"BYTECODELIES", (void *)NULL);
		goto procError;
	    }

	    /*
	     * Compare the default value if any.
	     */

	    if (localPtr->defValuePtr != NULL) {
		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) {

		    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", (void *)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) + 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
	int result;
	Tcl_Obj obj;

	obj.bytes = (char *) name;
	obj.length = strlen(name);
	obj.typePtr = NULL;
	result = TclObjGetFrame(interp, &obj, framePtrPtr);
	TclFreeIntRep(&obj);
	return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TclObjGetFrame --







|







722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
	int result;
	Tcl_Obj obj;

	obj.bytes = (char *) name;
	obj.length = strlen(name);
	obj.typePtr = NULL;
	result = TclObjGetFrame(interp, &obj, framePtrPtr);
	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
    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 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);
	if (w < 0 || w > INT_MAX || curLevel > w + INT_MAX) {
	    result = -1;
	} else {
	    level = curLevel - level;
	    result = 1;
	}
    } else if ((irPtr = TclFetchIntRep(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;

		    ir.wideValue = level;
		    Tcl_StoreIntRep(objPtr, &levelReferenceType, &ir);
		    result = 1;
		}
	    } else {
		result = -1;
	    }
	} else if (TclGetWideBitsFromObj(NULL, objPtr, &w) == TCL_OK) {
	    /*







|


















|






|









|


|







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
    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_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)) {
	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 = 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_ObjInternalRep ir;

		    ir.wideValue = level;
		    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
	    }
	    level = curLevel - 1;
	}
	if (level >= 0) {
	    CallFrame *framePtr;
	    for (framePtr = iPtr->varFramePtr; framePtr != NULL;
		    framePtr = framePtr->callerVarPtr) {
		if (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);
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UplevelObjCmd --







|











|







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
	    }
	    level = curLevel - 1;
	}
	if (level >= 0) {
	    CallFrame *framePtr;
	    for (framePtr = iPtr->varFramePtr; framePtr != NULL;
		    framePtr = framePtr->callerVarPtr) {
		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, (void *)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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Uplevel_Callback(
    ClientData 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,
    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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    Interp *iPtr = (Interp *) interp;
    CmdFrame *invoker = NULL;







|




















|









|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Uplevel_Callback(
    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(
    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(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
    *    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);
	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;
	    }







|
>
|







917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
    *    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;
	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
static int
ProcWrongNumArgs(
    Tcl_Interp *interp,
    int skip)
{
    CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
    Proc *procPtr = framePtr->procPtr;
    int 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);

	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);
	    } else if (defPtr->flags & VAR_IS_ARGS) {
		numArgs--;
		final = "?arg ...?";
		break;
	    } else {
		argObj = namePtr;
		Tcl_IncrRefCount(namePtr);







|



















|







|







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
static int
ProcWrongNumArgs(
    Tcl_Interp *interp,
    int skip)
{
    CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
    Proc *procPtr = framePtr->procPtr;
    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);

	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), "?", (void *)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
}

void
TclFreeLocalCache(
    Tcl_Interp *interp,
    LocalCache *localCachePtr)
{
    int 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_Obj **namePtr;
    Var *varPtr;
    LocalCache *localCachePtr;
    CompiledLocal *localPtr;
    int isNew;

    ByteCodeGetIntRep(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,
		    &isNew, /* nsPtr */ NULL, 0, NULL);
	    Tcl_IncrRefCount(*namePtr);
	}

	if (i < numArgs) {
	    varPtr->flags = (localPtr->flags & VAR_IS_ARGS);
	    varPtr->value.objPtr = localPtr->defValuePtr;







|



















|
|







|



















|







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
}

void
TclFreeLocalCache(
    Tcl_Interp *interp,
    LocalCache *localCachePtr)
{
    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;
    Tcl_Size localCt = procPtr->numCompiledLocals;
    Tcl_Size numArgs = procPtr->numArgs, i = 0;

    Tcl_Obj **namePtr;
    Var *varPtr;
    LocalCache *localCachePtr;
    CompiledLocal *localPtr;
    int isNew;

    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 */ 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;
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
    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_Obj *const *argObjs;

    ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);

    /*
     * Make sure that the local cache of variable names and initial values has
     * been initialised properly .
     */

    if (localCt) {







|


|







1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
    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;
    Tcl_Size localCt = procPtr->numCompiledLocals, numArgs, argCt, i, imax;
    Tcl_Obj *const *argObjs;

    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
     * 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;
	}
    }

    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'.
	 */








<







>







1385
1386
1387
1388
1389
1390
1391

1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
     * 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. */

    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
    /*
     * 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);

	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;







|







1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
    /*
     * 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)? 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
 *	to be popped by the caller.
 *
 *----------------------------------------------------------------------
 */

int
TclPushProcCallFrame(
    ClientData 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 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);
    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).

	 */

	if (((Interp *) *codePtr->interpHandle != iPtr)
		|| (codePtr->compileEpoch != iPtr->compileEpoch)
		|| (codePtr->nsPtr != nsPtr)
		|| (codePtr->nsEpoch != nsPtr->resolverEpoch)) {

	    goto doCompilation;
	}
    } else {
    doCompilation:
	result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr, nsPtr,
		(isLambda ? "body of lambda term" : "body of proc"),
		TclGetString(objv[isLambda]));







|



|



















|










>





|
>







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
 *	to be popped by the caller.
 *
 *----------------------------------------------------------------------
 */

int
TclPushProcCallFrame(
    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. */
    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.
     */

    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->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
 *	Depends on the commands in the procedure.
 *
 *----------------------------------------------------------------------
 */

int
TclObjInterpProc(
    ClientData 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. */
{
    /*
     * Not used much in the core; external interface for iTcl
     */

    return Tcl_NRCallObjProc(interp, TclNRInterpProc, clientData, objc, objv);
}

int
TclNRInterpProc(
    ClientData 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);
}



















/*
 *----------------------------------------------------------------------
 *
 * TclNRInterpProcCore --
 *
 *	When a Tcl procedure, lambda term or anything else that works like a







|











|




|



|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	Depends on the commands in the procedure.
 *
 *----------------------------------------------------------------------
 */

int
TclObjInterpProc(
    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. */
{
    /*
     * Not used much in the core; external interface for iTcl
     */

    return Tcl_NRCallObjProc(interp, NRInterpProc, clientData, objc, objv);
}

int
TclNRInterpProc(
    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. */
{
    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
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
 */

int
TclNRInterpProcCore(
    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,
				 * 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;







|







1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
 */

int
TclNRInterpProcCore(
    Tcl_Interp *interp,/* Interpreter in which procedure was
				 * invoked. */
    Tcl_Obj *procNameObj,	/* Procedure name for error reporting. */
    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
	TclStackFree(interp, freePtr);	/* Free CallFrame. */
	return TCL_ERROR;
    }

#if defined(TCL_COMPILE_DEBUG)
    if (tclTraceExec >= 1) {
	CallFrame *framePtr = iPtr->varFramePtr;
	int 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;
	const char *a[10];
	int 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];

	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_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_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);

    TclNRAddCallback(interp, InterpProcNR2, procNameObj, errorProc,
	    NULL, NULL);
    return TclNRExecuteByteCode(interp, codePtr);
}

static int
InterpProcNR2(
    ClientData 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_DTRACE_PROC_RETURN(l < iPtr->varFramePtr->objc ?
		TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result);
    }
    if (procPtr->refCount-- <= 1) {
	TclProcCleanupProc(procPtr);
    }







|

















|

|











|






|







|













|








|










|







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
	TclStackFree(interp, freePtr);	/* Free CallFrame. */
	return TCL_ERROR;
    }

#if defined(TCL_COMPILE_DEBUG)
    if (tclTraceExec >= 1) {
	CallFrame *framePtr = iPtr->varFramePtr;
	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()) {
	Tcl_Size l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
	const char *a[10];
	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]; 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()) {
	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()) {
	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++;
    ByteCodeGetInternalRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);

    TclNRAddCallback(interp, InterpProcNR2, procNameObj, errorProc,
	    NULL, NULL);
    return TclNRExecuteByteCode(interp, codePtr);
}

static int
InterpProcNR2(
    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()) {
	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

    if (result != TCL_OK) {
	goto process;
    }

    done:
    if (TCL_DTRACE_PROC_RESULT_ENABLED()) {
	int 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);
    }








|







1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829

    if (result != TCL_OK) {
	goto process;
    }

    done:
    if (TCL_DTRACE_PROC_RESULT_ENABLED()) {
	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
	 * 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);
	result = TCL_ERROR;

	/* FALLTHRU */

    case TCL_ERROR:
	/*
	 * Now it _must_ be an error, so we need to log it as such. This means







|







1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
	 * 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", (void *)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
    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);

    /*
     * 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.
     *

     * 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)) {

	    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);
		return TCL_ERROR;
	    }
	    codePtr->compileEpoch = iPtr->compileEpoch;
	    codePtr->nsPtr = nsPtr;
	} else {
	    Tcl_StoreIntRep(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);
	    fprintf(stdout, "%s\"\n", TclGetString(message));
	    Tcl_DecrRefCount(message);
	}
#else
    (void)description;
    (void)procName;
#endif







|











>








|
>








|





|


















|
|







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
    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;

    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->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", (void *)NULL);
		return TCL_ERROR;
	    }
	    codePtr->compileEpoch = iPtr->compileEpoch;
	    codePtr->nsPtr = nsPtr;
	} else {
	    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, " \"", (void *)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
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
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;
    const char *procName = TclGetStringFromObj(procNameObj, &nameLen);

    overflow = (nameLen > limit);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (procedure \"%.*s%s\" line %d)",
	    (int)(overflow ? limit :nameLen), procName,
	    (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
}

/*
 *----------------------------------------------------------------------
 *
 * TclProcDeleteProc --







|
|


|


|







2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
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. */
{
    int overflow, limit = 60;
    Tcl_Size nameLen;
    const char *procName = TclGetStringFromObj(procNameObj, &nameLen);

    overflow = (nameLen > (Tcl_Size)limit);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (procedure \"%.*s%s\" line %d)",
	    (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
 *	procedure completes.
 *
 *----------------------------------------------------------------------
 */

void
TclProcDeleteProc(
    ClientData clientData)	/* Procedure to be deleted. */
{
    Proc *procPtr = (Proc *)clientData;

    if (procPtr->refCount-- <= 1) {
	TclProcCleanupProc(procPtr);
    }
}







|







2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
 *	procedure completes.
 *
 *----------------------------------------------------------------------
 */

void
TclProcDeleteProc(
    void *clientData)	/* Procedure to be deleted. */
{
    Proc *procPtr = (Proc *)clientData;

    if (procPtr->refCount-- <= 1) {
	TclProcCleanupProc(procPtr);
    }
}
2100
2101
2102
2103
2104
2105
2106







2107
2108
2109
2110
2111
2112
2113
    Tcl_Obj *defPtr;
    Tcl_ResolvedVarInfo *resVarInfo;
    Tcl_HashEntry *hePtr = NULL;
    CmdFrame *cfPtr = NULL;
    Interp *iPtr = procPtr->iPtr;

    if (bodyPtr != NULL) {







	Tcl_DecrRefCount(bodyPtr);
    }
    for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; ) {
	CompiledLocal *nextPtr = localPtr->nextPtr;

	resVarInfo = localPtr->resolveInfo;
	if (resVarInfo) {







>
>
>
>
>
>
>







2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
    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) {
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
    }
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetObjInterpProc --
 *
 *	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.
 *
 * Results:
 *	Returns the internal address of the TclObjInterpProc function.

 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

TclObjCmdProcType
TclGetObjInterpProc(void)
{
    return (TclObjCmdProcType) TclObjInterpProc;






}

/*
 *----------------------------------------------------------------------
 *
 * TclNewProcBodyObj --
 *







|

|
|
|
|


|
>







|


|
>
>
>
>
>
>







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
    }
    return code;
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetObjInterpProc/TclGetObjInterpProc2 --
 *
 *	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/ObjInterpProc2
 *	functions.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_ObjCmdProc *
TclGetObjInterpProc(void)
{
    return TclObjInterpProc;
}

Tcl_ObjCmdProc2 *
TclGetObjInterpProc2(void)
{
    return ObjInterpProc2;
}

/*
 *----------------------------------------------------------------------
 *
 * TclNewProcBodyObj --
 *
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271

    if (!procPtr) {
	return NULL;
    }

    TclNewObj(objPtr);
    if (objPtr) {
	ProcSetIntRep(objPtr, procPtr);
    }

    return objPtr;
}

/*
 *----------------------------------------------------------------------







|







2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329

    if (!procPtr) {
	return NULL;
    }

    TclNewObj(objPtr);
    if (objPtr) {
	ProcSetInternalRep(objPtr, procPtr);
    }

    return objPtr;
}

/*
 *----------------------------------------------------------------------
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302

static void
ProcBodyDup(
    Tcl_Obj *srcPtr,		/* Object to copy. */
    Tcl_Obj *dupPtr)		/* Target object for the duplication. */
{
    Proc *procPtr;
    ProcGetIntRep(srcPtr, procPtr);

    ProcSetIntRep(dupPtr, procPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ProcBodyFree --
 *







|

|







2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360

static void
ProcBodyDup(
    Tcl_Obj *srcPtr,		/* Object to copy. */
    Tcl_Obj *dupPtr)		/* Target object for the duplication. */
{
    Proc *procPtr;
    ProcGetInternalRep(srcPtr, procPtr);

    ProcSetInternalRep(dupPtr, procPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * ProcBodyFree --
 *
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330

static void
ProcBodyFree(
    Tcl_Obj *objPtr)		/* The object to clean up. */
{
    Proc *procPtr;

    ProcGetIntRep(objPtr, procPtr);

    if (procPtr->refCount-- <= 1) {
	TclProcCleanupProc(procPtr);
    }
}

/*







|







2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388

static void
ProcBodyFree(
    Tcl_Obj *objPtr)		/* The object to clean up. */
{
    Proc *procPtr;

    ProcGetInternalRep(objPtr, procPtr);

    if (procPtr->refCount-- <= 1) {
	TclProcCleanupProc(procPtr);
    }
}

/*
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
DupLambdaInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
{
    Proc *procPtr;
    Tcl_Obj *nsObjPtr;

    LambdaGetIntRep(srcPtr, procPtr, nsObjPtr);
    assert(procPtr != NULL);

    procPtr->refCount++;

    LambdaSetIntRep(copyPtr, procPtr, nsObjPtr);
}

static void
FreeLambdaInternalRep(
    Tcl_Obj *objPtr)	/* CmdName object with internal representation
				 * to free. */
{
    Proc *procPtr;
    Tcl_Obj *nsObjPtr;

    LambdaGetIntRep(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. */
{
    Interp *iPtr = (Interp *) interp;
    const char *name;
    Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv;
    int isNew, objc, result;

    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 = 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);
	return TCL_ERROR;
    }

    argsPtr = objv[0];
    bodyPtr = objv[1];

    /*







|




|










|
















|
>












>
>
>
>
>
>
>
>





|







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
DupLambdaInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)	/* Object with internal rep to set. */
{
    Proc *procPtr;
    Tcl_Obj *nsObjPtr;

    LambdaGetInternalRep(srcPtr, procPtr, nsObjPtr);
    assert(procPtr != NULL);

    procPtr->refCount++;

    LambdaSetInternalRep(copyPtr, procPtr, nsObjPtr);
}

static void
FreeLambdaInternalRep(
    Tcl_Obj *objPtr)	/* CmdName object with internal representation
				 * to free. */
{
    Proc *procPtr;
    Tcl_Obj *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. */
{
    Interp *iPtr = (Interp *) interp;
    const char *name;
    Tcl_Obj *argsPtr, *bodyPtr, *nsObjPtr, **objv;
    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", (void *)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", (void *)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
	    /*
	     * 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];

		/*
		 * 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[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);







|











|







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
	    /*
	     * 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)) {
		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 = (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
     */

    if (objc == 2) {
	TclNewLiteralStringObj(nsObjPtr, "::");
    } else {
	const char *nsName = TclGetString(objv[2]);

	if ((*nsName != ':') || (*(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);
    return TCL_OK;
}

Proc *
TclGetLambdaFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Obj **nsObjPtrPtr)
{
    Proc *procPtr;
    Tcl_Obj *nsObjPtr;

    LambdaGetIntRep(objPtr, procPtr, nsObjPtr);

    if (procPtr == NULL) {
	if (SetLambdaFromAny(interp, objPtr) != TCL_OK) {
	    return NULL;
	}
	LambdaGetIntRep(objPtr, procPtr, nsObjPtr);
    }

    assert(procPtr != NULL);
    if (procPtr->iPtr != (Interp *)interp) {
	return NULL;
    }








|













|












|





|







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
     */

    if (objc == 2) {
	TclNewLiteralStringObj(nsObjPtr, "::");
    } else {
	const char *nsName = TclGetString(objv[2]);

	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.
     */

    LambdaSetInternalRep(objPtr, procPtr, nsObjPtr);
    return TCL_OK;
}

Proc *
TclGetLambdaFromObj(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Obj **nsObjPtrPtr)
{
    Proc *procPtr;
    Tcl_Obj *nsObjPtr;

    LambdaGetInternalRep(objPtr, procPtr, nsObjPtr);

    if (procPtr == NULL) {
	if (SetLambdaFromAny(interp, objPtr) != TCL_OK) {
	    return NULL;
	}
	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
 *	Depends on the content of the lambda term (i.e., objv[1]).
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ApplyObjCmd(
    ClientData 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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Proc *procPtr = NULL;
    Tcl_Obj *lambdaPtr, *nsObjPtr;
    int result;







|









|







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
 *	Depends on the content of the lambda term (i.e., objv[1]).
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ApplyObjCmd(
    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(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
	result = TclNRInterpProcCore(interp, objv[1], 2, &MakeLambdaError);
    }
    return result;
}

static int
ApplyNR2(
    ClientData data[],
    Tcl_Interp *interp,
    int result)
{
    ApplyExtraData *extraPtr = (ApplyExtraData *)data[0];

    TclStackFree(interp, extraPtr);
    return result;







|







2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
	result = TclNRInterpProcCore(interp, objv[1], 2, &MakeLambdaError);
    }
    return result;
}

static int
ApplyNR2(
    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
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;
    const char *procName = TclGetStringFromObj(procNameObj, &nameLen);

    overflow = (nameLen > limit);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (lambda term \"%.*s%s\" line %d)",
	    (int)(overflow ? limit : nameLen), procName,
	    (overflow ? "..." : ""), Tcl_GetErrorLine(interp)));
}

/*
 *----------------------------------------------------------------------
 *
 * TclGetCmdFrameForProcedure --







|
|


|


|







2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
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. */
{
    int overflow, limit = 60;
    Tcl_Size nameLen;
    const char *procName = TclGetStringFromObj(procNameObj, &nameLen);

    overflow = (nameLen > (Tcl_Size)limit);
    Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
	    "\n    (lambda term \"%.*s%s\" line %d)",
	    (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
/*
 * tclProcess.c --
 *
 *	This file implements the "tcl::process" ensemble for subprocess
 *	management as defined by TIP #462.
 *
 * 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.
 */

#include "tclInt.h"







|







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 © 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

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. */
    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);
static void		FreeProcessInfo(ProcessInfo *info);
static int		RefreshProcessInfo(ProcessInfo *info, int options);
static TclProcessWaitStatus WaitProcessStatus(Tcl_Pid pid, size_t resolvedPid,
			    int options, int *codePtr, Tcl_Obj **msgPtr,
			    Tcl_Obj **errorObjPtr);
static Tcl_Obj *	BuildProcessStatusObj(ProcessInfo *info);
static int		ProcessListObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		ProcessStatusObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		ProcessPurgeObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);
static int		ProcessAutopurgeObjCmd(ClientData clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const objv[]);

/*
 *----------------------------------------------------------------------
 *
 * InitProcessInfo --
 *
 *	Initializes the ProcessInfo structure.







|



>










|


|



|
<
<
|
<
<
|
<
<
|
<
<







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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. */
    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,
			    Tcl_Size resolvedPid);
static void		FreeProcessInfo(ProcessInfo *info);
static int		RefreshProcessInfo(ProcessInfo *info, int options);
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 Tcl_ObjCmdProc ProcessListObjCmd;


static Tcl_ObjCmdProc ProcessStatusObjCmd;


static Tcl_ObjCmdProc ProcessPurgeObjCmd;


static Tcl_ObjCmdProc ProcessAutopurgeObjCmd;



/*
 *----------------------------------------------------------------------
 *
 * InitProcessInfo --
 *
 *	Initializes the ProcessInfo structure.
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
 *----------------------------------------------------------------------
 */

void
InitProcessInfo(
    ProcessInfo *info,		/* Structure to initialize. */
    Tcl_Pid pid,		/* Process id. */
    int resolvedPid)		/* Resolved process id. */
{
    info->pid = pid;
    info->resolvedPid = resolvedPid;
    info->purge = 0;
    info->status = TCL_PROCESS_UNCHANGED;
    info->code = 0;
    info->msg = NULL;







|







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. */
    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
 *
 *----------------------------------------------------------------------
 */

int
RefreshProcessInfo(
    ProcessInfo *info,		/* Structure to refresh. */
    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) Tcl_IncrRefCount(info->msg);

	if (info->error) Tcl_IncrRefCount(info->error);


	return (info->status != TCL_PROCESS_UNCHANGED);
    } else {
	/*
	 * No change.
	 */

	return 0;







|
<








>
|
>
|
>
>







141
142
143
144
145
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. */

{
    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) {
	    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
 *
 *----------------------------------------------------------------------
 */

TclProcessWaitStatus
WaitProcessStatus(
    Tcl_Pid pid,		/* Process id. */
    size_t 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_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;








|






|
<







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. */
    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_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
	     * 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 (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) *codePtr = WEXITSTATUS(waitStatus);

	if (!WEXITSTATUS(waitStatus)) {
	    /*
	     * Normal exit.
	     */

	    if (msgObjPtr) *msgObjPtr = NULL;


	    if (errorObjPtr) *errorObjPtr = NULL;


	} else {
	    /*
	     * CHILDSTATUS pid code
	     *
	     * Child exited with a non-zero exit status.
	     */


	    if (msgObjPtr) *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) *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) *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 (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);







|
>
>
>
|
|
>








>
|
>





|
>
>
|
>
>







>
|
|
>
















>
|
>
|
|
>
















>
|
>
|
|
>















|
>
>
>
|
|
>







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
	     * 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 (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) {
	    *codePtr = WEXITSTATUS(waitStatus);
	}
	if (!WEXITSTATUS(waitStatus)) {
	    /*
	     * Normal exit.
	     */

	    if (msgObjPtr) {
		*msgObjPtr = NULL;
	    }
	    if (errorObjPtr) {
		*errorObjPtr = NULL;
	    }
	} else {
	    /*
	     * CHILDSTATUS pid code
	     *
	     * Child exited with a non-zero exit status.
	     */

	    if (msgObjPtr) {
		*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) {
	    *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) {
	    *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 (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);
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
 *	Access to the internal structures is protected by infoTablesMutex.
 *
 *----------------------------------------------------------------------
 */

static int
ProcessListObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
 *	Access to the internal structures is protected by infoTablesMutex.
 *
 *----------------------------------------------------------------------
 */

static int
ProcessListObjCmd(
    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
 *	Calls RefreshProcessInfo, which can block if -wait switch is given.
 *
 *----------------------------------------------------------------------
 */

static int
ProcessStatusObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *dict;
    int index, options = WNOHANG;
    Tcl_HashEntry *entry;
    Tcl_HashSearch search;
    ProcessInfo *info;
    int 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
    };

    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) {
	    options = 0;
	} else {
	    break;
	}
    }

    if (objc != 1 && objc != 2) {







|





|



|


<







|










|







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
 *	Calls RefreshProcessInfo, which can block if -wait switch is given.
 *
 *----------------------------------------------------------------------
 */

static int
ProcessStatusObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *dict;
    int options = WNOHANG;
    Tcl_HashEntry *entry;
    Tcl_HashSearch search;
    ProcessInfo *info;
    Tcl_Size i, numPids;
    Tcl_Obj **pidObjs;
    int result;

    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 == index) {
	    options = 0;
	} else {
	    break;
	}
    }

    if (objc != 1 && objc != 2) {
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
	}
	Tcl_MutexUnlock(&infoTablesMutex);
    } else {
	/*
	 * Only return statuses of provided processes.
	 */

	result = Tcl_ListObjGetElements(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);







|







545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
	}
	Tcl_MutexUnlock(&infoTablesMutex);
    } else {
	/*
	 * Only return statuses of provided processes.
	 */

	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);
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
 *	Frees all ProcessInfo structures with their purge flag set.
 *
 *----------------------------------------------------------------------
 */

static int
ProcessPurgeObjCmd(
    TCL_UNUSED(ClientData),
    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_Obj **pidObjs;
    int result;
    int i;
    int pid;

    if (objc != 1 && objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?pids?");
	return TCL_ERROR;
    }

    /*







|







|

|
<
<







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
 *	Frees all ProcessInfo structures with their purge flag set.
 *
 *----------------------------------------------------------------------
 */

static int
ProcessPurgeObjCmd(
    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;
    Tcl_Size i, numPids;
    Tcl_Obj **pidObjs;
    int result, 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
	}
	Tcl_MutexUnlock(&infoTablesMutex);
    } else {
	/*
	 * Purge only provided processes.
	 */

	result = Tcl_ListObjGetElements(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) {







|







658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
	}
	Tcl_MutexUnlock(&infoTablesMutex);
    } else {
	/*
	 * Purge only provided processes.
	 */

	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
 *	Alters detached process handling by Tcl_ReapDetachedProcs().
 *
 *----------------------------------------------------------------------
 */

static int
ProcessAutopurgeObjCmd(
    TCL_UNUSED(ClientData),
    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?");







|







711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
 *	Alters detached process handling by Tcl_ReapDetachedProcs().
 *
 *----------------------------------------------------------------------
 */

static int
ProcessAutopurgeObjCmd(
    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
 *----------------------------------------------------------------------
 */

void
TclProcessCreated(
    Tcl_Pid pid)		/* Process id. */
{
    size_t resolvedPid;
    Tcl_HashEntry *entry, *entry2;
    int isNew;
    ProcessInfo *info;

    /*
     * Get resolved pid first.
     */







|







810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
 *----------------------------------------------------------------------
 */

void
TclProcessCreated(
    Tcl_Pid pid)		/* Process id. */
{
    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
	/*
	 * Pid was reused, free old info and reuse structure.
	 */

	info = (ProcessInfo *) Tcl_GetHashValue(entry);
	entry2 = Tcl_FindHashEntry(&infoTablePerResolvedPid,
		INT2PTR(resolvedPid));

	if (entry2) Tcl_DeleteHashEntry(entry2);

	FreeProcessInfo(info);
    }

    /*
     * Allocate and initialize info structure.
     */








>
|
>







836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
	/*
	 * Pid was reused, free old info and reuse structure.
	 */

	info = (ProcessInfo *) Tcl_GetHashValue(entry);
	entry2 = Tcl_FindHashEntry(&infoTablePerResolvedPid,
		INT2PTR(resolvedPid));
	if (entry2) {
	    Tcl_DeleteHashEntry(entry2);
	}
	FreeProcessInfo(info);
    }

    /*
     * Allocate and initialize info structure.
     */

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
    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);
	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);


	return TCL_PROCESS_UNCHANGED;
    }

    RefreshProcessInfo(info, options);
    if (info->status == TCL_PROCESS_UNCHANGED) {
	/*
	 * No change, stop there.
	 */
    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 (autopurge) {
	/*
	 * Purge now.
	 */

	Tcl_DeleteHashEntry(entry);







|
>
>
|
>
>
|









<

>








<

>








|
>
>
|
>
>
|
>
>
|
>
>
|
>
>







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
    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);
	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);
	return TCL_PROCESS_UNCHANGED;
    }

    RefreshProcessInfo(info, options);
    if (info->status == TCL_PROCESS_UNCHANGED) {
	/*
	 * No change, stop there.
	 */


	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 (autopurge) {
	/*
	 * Purge now.
	 */

	Tcl_DeleteHashEntry(entry);
952
953
954
955
956
957
958








	 */

	info->purge = 1;
    }
    Tcl_MutexUnlock(&infoTablesMutex);
    return result;
}















>
>
>
>
>
>
>
>
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
	 */

	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
/*
 * 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.
 *
 * 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 <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.
 *
 * 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






|
|







>













|







1
2
3
4
5
6
7
8
9
10
11
12
13
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 © 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 © 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
 * 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		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 */

};

#define RegexpSetIntRep(objPtr, rePtr)					\
    do {								\
	Tcl_ObjIntRep ir;						\
	(rePtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (rePtr);					\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreIntRep((objPtr), &tclRegexpType, &ir);			\
    } while (0)

#define RegexpGetIntRep(objPtr, rePtr)					\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &tclRegexpType);		\
	(rePtr) = irPtr ? (TclRegexp *)irPtr->twoPtrValue.ptr1 : NULL;		\
    } while (0)


/*
 *----------------------------------------------------------------------
 *







|

















|
>


|

|



|


|

|
|







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
 * 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(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 */
    TCL_OBJTYPE_V0
};

#define RegexpSetInternalRep(objPtr, rePtr)					\
    do {								\
	Tcl_ObjInternalRep ir;						\
	(rePtr)->refCount++;						\
	ir.twoPtrValue.ptr1 = (rePtr);					\
	ir.twoPtrValue.ptr2 = NULL;					\
	Tcl_StoreInternalRep((objPtr), &tclRegexpType, &ir);			\
    } while (0)

#define RegexpGetInternalRep(objPtr, rePtr)					\
    do {								\
	const Tcl_ObjInternalRep *irPtr;					\
	irPtr = TclFetchInternalRep((objPtr), &tclRegexpType);		\
	(rePtr) = irPtr ? (TclRegexp *)irPtr->twoPtrValue.ptr1 : NULL;		\
    } while (0)


/*
 *----------------------------------------------------------------------
 *
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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),
	    REG_ADVANCED);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegExpExec --







|







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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, strlen(pattern),
	    REG_ADVANCED);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_RegExpExec --
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
    regexp->objPtr = NULL;

    /*
     * Convert the string to Unicode and perform the match.
     */

    Tcl_DStringInit(&ds);
    ustr = Tcl_UtfToUniCharDString(text, -1, &ds);
    numChars = Tcl_DStringLength(&ds) / sizeof(Tcl_UniChar);
    result = RegExpExecUniChar(interp, re, ustr, numChars, -1 /* nmatches */,
	    flags);
    Tcl_DStringFree(&ds);

    return result;
}

/*







|

|







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, TCL_INDEX_NONE, &ds);
    numChars = Tcl_DStringLength(&ds) / sizeof(Tcl_UniChar);
    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
 *---------------------------------------------------------------------------
 */

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,
				 * > 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) {
	*startPtr = *endPtr = NULL;
    } else if (regexpPtr->matches[index].rm_so == TCL_INDEX_NONE) {
	*startPtr = *endPtr = NULL;
    } else {
	if (regexpPtr->objPtr) {
	    string = TclGetString(regexpPtr->objPtr);
	} else {
	    string = regexpPtr->string;
	}







|










|

|







249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
 *---------------------------------------------------------------------------
 */

void
Tcl_RegExpRange(
    Tcl_RegExp re,		/* Compiled regular expression that has been
				 * passed to Tcl_RegExpExec. */
    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 < 0 || (size_t) index > regexpPtr->re.re_nsub) {
	*startPtr = *endPtr = NULL;
    } 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;
	}
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
 *---------------------------------------------------------------------------
 */

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,
				 * > 0 means give the range of a matching
				 * subrange, TCL_INDEX_NONE means the range of the
				 * rm_extend field. */
    size_t *startPtr,		/* Store address of first character in
				 * (sub-)range here. */
    size_t *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)) {
	*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 {
	*startPtr = regexpPtr->matches[index].rm_so;
	*endPtr = regexpPtr->matches[index].rm_eo;
    }
}

/*







|

|

|

|




|


|
|
|







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
 *---------------------------------------------------------------------------
 */

void
TclRegExpRangeUniChar(
    Tcl_RegExp re,		/* Compiled regular expression that has been
				 * passed to Tcl_RegExpExec. */
    Tcl_Size index,		/* 0 means give the range of the entire match,
				 * > 0 means give the range of a matching
				 * subrange, -1 means the range of the
				 * rm_extend field. */
    Tcl_Size *startPtr,	/* Store address of first character in
				 * (sub-)range here. */
    Tcl_Size *endPtr)	/* Store address of character just after last
				 * in (sub-)range here. */
{
    TclRegexp *regexpPtr = (TclRegexp *) re;

    if ((regexpPtr->flags&REG_EXPECT) && (index == -1)) {
	*startPtr = regexpPtr->details.rm_extend.rm_so;
	*endPtr = regexpPtr->details.rm_extend.rm_eo;
    } 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
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
				 * should begin. */
    size_t 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;
    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)







|

|






|







439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
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. */
    Tcl_Size offset,		/* Character index that marks where matching
				 * should begin. */
    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;
    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
    /*
     * Save the target object so we can extract strings from it later.
     */

    regexpPtr->string = NULL;
    regexpPtr->objPtr = textObj;

    udata = TclGetUnicodeFromObj(textObj, &length);

    if (offset > length) {
	offset = length;
    }
    udata += offset;
    length -= offset;








|







479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
    /*
     * Save the target object so we can extract strings from it later.
     */

    regexpPtr->string = NULL;
    regexpPtr->objPtr = textObj;

    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
     * 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))) {
	return -1;
    }
    return Tcl_RegExpExecObj(interp, re, textObj, 0 /* offset */,
	    0 /* nmatches */, 0 /* flags */);
}

/*







|
|







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
     * 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))) {
	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
				 * 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;
    TclRegexp *regexpPtr;
    const char *pattern;

    RegexpGetIntRep(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);
    }
    return (Tcl_RegExp) regexpPtr;
}

/*
 *----------------------------------------------------------------------
 *







|



|









|







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
				 * 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. */
{
    Tcl_Size length;
    TclRegexp *regexpPtr;
    const char *pattern;

    RegexpGetInternalRep(objPtr, regexpPtr);

    if ((regexpPtr == NULL) || (regexpPtr->flags != flags)) {
	pattern = TclGetStringFromObj(objPtr, &length);

	regexpPtr = CompileRegexp(interp, pattern, length, flags);
	if (regexpPtr == NULL) {
	    return NULL;
	}

	RegexpSetInternalRep(objPtr, regexpPtr);
    }
    return (Tcl_RegExp) regexpPtr;
}

/*
 *----------------------------------------------------------------------
 *
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
    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);
    (void) TclReError(REG_ITOA, cbuf, sizeof(cbuf));
    Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeRegexpInternalRep --
 *







|

|







726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
    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));

    snprintf(cbuf, sizeof(cbuf), "%d", status);
    (void) TclReError(REG_ITOA, cbuf, sizeof(cbuf));
    Tcl_SetErrorCode(interp, "REGEXP", cbuf, buf, (char *)NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * FreeRegexpInternalRep --
 *
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766

static void
FreeRegexpInternalRep(
    Tcl_Obj *objPtr)		/* Regexp object with internal rep to free. */
{
    TclRegexp *regexpRepPtr;

    RegexpGetIntRep(objPtr, regexpRepPtr);

    assert(regexpRepPtr != NULL);

    /*
     * If this is the last reference to the regexp, free it.
     */








|







754
755
756
757
758
759
760
761
762
763
764
765
766
767
768

static void
FreeRegexpInternalRep(
    Tcl_Obj *objPtr)		/* Regexp object with internal rep to free. */
{
    TclRegexp *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
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);

    assert(regexpPtr != NULL);

    RegexpSetIntRep(copyPtr, regexpPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * SetRegexpFromAny --
 *







|



|







791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
static void
DupRegexpInternalRep(
    Tcl_Obj *srcPtr,		/* Object with internal rep to copy. */
    Tcl_Obj *copyPtr)		/* Object with internal rep to set. */
{
    TclRegexp *regexpPtr;

    RegexpGetInternalRep(srcPtr, regexpPtr);

    assert(regexpPtr != NULL);

    RegexpSetInternalRep(copyPtr, regexpPtr);
}

/*
 *----------------------------------------------------------------------
 *
 * SetRegexpFromAny --
 *
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
    /*
     * 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;

    /*
     * Get the up-to-date string representation and map to unicode.
     */

    Tcl_DStringInit(&stringBuf);
    uniString = Tcl_UtfToUniCharDString(string, length, &stringBuf);







|
|







916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
    /*
     * 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 = 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);
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
     * 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);
	Tcl_IncrRefCount(regexpPtr->globObjPtr);
    } else {
	regexpPtr->globObjPtr = NULL;
    }

    /*
     * Allocate enough space for all of the subexpressions, plus one extra for







|







956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
     * 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 = 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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
FinalizeRegexp(
    TCL_UNUSED(ClientData))
{
    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];







|







1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
FinalizeRegexp(
    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/tclResolve.c.

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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"









|







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 © 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
/*
 * tclResult.c --
 *
 *	This file contains code to manage the interpreter result.
 *
 * Copyright (c) 1997 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.
 */

#include "tclInt.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		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.
 */





|






>















|







1
2
3
4
5
6
7
8
9
10
11
12
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 © 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(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
    Tcl_Free(statePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetObjResult --
 *
 *	Arrange for objPtr to be an interpreter's result value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	interp->objResultPtr is left pointing to the object referenced by
 *	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.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetObjResult(
    Tcl_Interp *interp,		/* Interpreter with which to associate the
				 * return object value. */
    Tcl_Obj *objPtr)	/* Tcl object to be returned. If NULL, the obj
				 * 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 */

    /*
     * We wait until the end to release the old object result, in case we are
     * setting the result to itself.
     */

    TclDecrRefCount(oldObjResult);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetObjResult --
 *







<
|





|
<
|
>
|






|
<
|
<



|
>
>
>
>
|
|
|
<
<
<
<
|
<







208
209
210
211
212
213
214

215
216
217
218
219
220
221

222
223
224
225
226
227
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 --

 *	Makes objPtr the interpreter's result value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Stores objPtr interp->objResultPtr, increments its reference count, and

 *	decrements the reference count of any existing interp->objResultPtr.
 *
 *	The string result is reset.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetObjResult(
    Tcl_Interp *interp,		/* Interpreter to set the result for. */

    Tcl_Obj *objPtr)		/* The value to set as the result. */

{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *oldObjResult = iPtr->objResultPtr;
    if (objPtr == oldObjResult) {
	/* This should be impossible */
	assert(objPtr->refCount != 0);
	return;
    } else {
	iPtr->objResultPtr = objPtr;
	Tcl_IncrRefCount(objPtr);
	TclDecrRefCount(oldObjResult);




    }

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetObjResult --
 *
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    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;

    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);







|







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;
    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);
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
	if (objResultPtr->bytes != &tclEmptyString) {
	    if (objResultPtr->bytes) {
		Tcl_Free(objResultPtr->bytes);
	    }
	    objResultPtr->bytes = &tclEmptyString;
	    objResultPtr->length = 0;
	}
	TclFreeIntRep(objResultPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetErrorCode --







|







455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
	if (objResultPtr->bytes != &tclEmptyString) {
	    if (objResultPtr->bytes) {
		Tcl_Free(objResultPtr->bytes);
	    }
	    objResultPtr->bytes = &tclEmptyString;
	    objResultPtr->length = 0;
	}
	TclFreeInternalRep(objResultPtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetErrorCode --
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508

    /*
     * Scan through the arguments one at a time, appending them to the
     * errorCode field as list elements.
     */

    va_start(argList, interp);
    errorObj = Tcl_NewObj();

    /*
     * Scan through the arguments one at a time, appending them to the
     * errorCode field as list elements.
     */

    while (1) {







|







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);
    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
 *	Frees memory.
 *
 *----------------------------------------------------------------------
 */

static void
ReleaseKeys(
    ClientData clientData)
{
    Tcl_Obj **keys = (Tcl_Obj **)clientData;
    int i;

    for (i = KEY_CODE; i < KEY_LAST; i++) {
	Tcl_DecrRefCount(keys[i]);
	keys[i] = NULL;







|







652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
 *	Frees memory.
 *
 *----------------------------------------------------------------------
 */

static void
ReleaseKeys(
    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;
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
	if (iPtr->errorInfo) {
	    Tcl_DecrRefCount(iPtr->errorInfo);
	    iPtr->errorInfo = NULL;
	}
	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO],
                &valuePtr);
	if (valuePtr != NULL) {
	    size_t 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);
	if (valuePtr != NULL) {
            int len, valueObjc;
            Tcl_Obj **valueObjv;

            if (Tcl_IsShared(iPtr->errorStack)) {
                Tcl_Obj *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]]
             */

            if (Tcl_ListObjGetElements(interp, valuePtr, &valueObjc,
                    &valueObjv) == TCL_ERROR) {
                return TCL_ERROR;
            }
            iPtr->resetErrorStack = 0;
            Tcl_ListObjLength(interp, iPtr->errorStack, &len);

            /*
             * Reset while keeping the list intrep as much as possible.
             */

            Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, valueObjc,
                    valueObjv);
 	}
	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE],
                &valuePtr);
	if (valuePtr != NULL) {
	    Tcl_SetObjErrorCode(interp, valuePtr);
	} else {
	    Tcl_SetErrorCode(interp, "NONE", NULL);
	}

	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE],
                &valuePtr);
	if (valuePtr != NULL) {
	    TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine);
	}







|

|









|
















|




|


|










|







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
	if (iPtr->errorInfo) {
	    Tcl_DecrRefCount(iPtr->errorInfo);
	    iPtr->errorInfo = NULL;
	}
	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORINFO],
                &valuePtr);
	if (valuePtr != NULL) {
	    Tcl_Size 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);
	if (valuePtr != NULL) {
            Tcl_Size len, valueObjc;
            Tcl_Obj **valueObjv;

            if (Tcl_IsShared(iPtr->errorStack)) {
                Tcl_Obj *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]]
             */

            if (TclListObjGetElements(interp, valuePtr, &valueObjc,
                    &valueObjv) == TCL_ERROR) {
                return TCL_ERROR;
            }
            iPtr->resetErrorStack = 0;
            TclListObjLength(interp, iPtr->errorStack, &len);

            /*
             * Reset while keeping the list internalrep as much as possible.
             */

            Tcl_ListObjReplace(interp, iPtr->errorStack, 0, len, valueObjc,
                    valueObjv);
 	}
	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORCODE],
                &valuePtr);
	if (valuePtr != NULL) {
	    Tcl_SetObjErrorCode(interp, valuePtr);
	} else {
	    Tcl_SetErrorCode(interp, "NONE", (void *)NULL);
	}

	Tcl_DictObjGet(NULL, iPtr->returnOpts, keys[KEY_ERRORLINE],
                &valuePtr);
	if (valuePtr != NULL) {
	    TclGetIntFromObj(NULL, valuePtr, &iPtr->errorLine);
	}
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
		 * Value is not a legal dictionary.
		 */

		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "bad %s value: expected dictionary but got \"%s\"",
                        compare, TclGetString(objv[1])));
		Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS",
			NULL);
		goto error;
	    }

	    while (!done) {
		Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr);
		Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
	    }







|







842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
		 * Value is not a legal dictionary.
		 */

		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "bad %s value: expected dictionary but got \"%s\"",
                        compare, TclGetString(objv[1])));
		Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_OPTIONS",
			(void *)NULL);
		goto error;
	    }

	    while (!done) {
		Tcl_DictObjPut(NULL, returnOpts, keyPtr, valuePtr);
		Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done);
	    }
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
	    /*
	     * 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);
	    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;

	if (TCL_ERROR == Tcl_ListObjLength(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)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_ERRORCODE",
		    NULL);
	    goto error;
	}
    }

    /*
     * Check for bogus -errorstack value.
     */

    Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORSTACK], &valuePtr);
    if (valuePtr != NULL) {
	int length;

	if (TCL_ERROR == Tcl_ListObjLength(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)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT", "NONLIST_ERRORSTACK",
                    NULL);
	    goto error;
	}
        if (length % 2) {
            /*
             * Errorstack must always be an even-sized list
             */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "forbidden odd-sized list for -errorstack: \"%s\"",
		    TclGetString(valuePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT",
                    "ODDSIZEDLIST_ERRORSTACK", NULL);
	    goto error;
        }
    }

    /*
     * Convert [return -code return -level X] to [return -code ok -level X+1]
     */







|











|

|








|










|

|








|











|







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
	    /*
	     * 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", (void *)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) {
	Tcl_Size 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)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT", "ILLEGAL_ERRORCODE",
		    (void *)NULL);
	    goto error;
	}
    }

    /*
     * Check for bogus -errorstack value.
     */

    Tcl_DictObjGet(NULL, returnOpts, keys[KEY_ERRORSTACK], &valuePtr);
    if (valuePtr != NULL) {
	Tcl_Size 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)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT", "NONLIST_ERRORSTACK",
                    (void *)NULL);
	    goto error;
	}
        if (length % 2) {
            /*
             * Errorstack must always be an even-sized list
             */

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "forbidden odd-sized list for -errorstack: \"%s\"",
		    TclGetString(valuePtr)));
	    Tcl_SetErrorCode(interp, "TCL", "RESULT",
                    "ODDSIZEDLIST_ERRORSTACK", (void *)NULL);
	    goto error;
        }
    }

    /*
     * Convert [return -code return -level X] to [return -code ok -level X+1]
     */
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
 */

int
Tcl_SetReturnOptions(
    Tcl_Interp *interp,
    Tcl_Obj *options)
{

    int objc, 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);
	code = TCL_ERROR;
    } else if (TCL_ERROR == TclMergeReturnOptions(interp, objc, objv,
	    &mergedOpts, &code, &level)) {
	code = TCL_ERROR;
    } else {
	code = TclProcessReturn(interp, code, level, mergedOpts);
    }







>
|







|







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 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", (void *)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
/*
 * tclScan.c --
 *
 *	This file contains the implementation of the "scan" command.
 *
 * Copyright (c) 1998 by 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"


/*
 * Flag values used by Tcl_ScanObjCmd.
 */

#define SCAN_NOSKIP	0x1		/* Don't skip blanks. */
#define SCAN_SUPPRESS	0x2		/* Suppress assignment. */





|







>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * tclScan.c --
 *
 *	This file contains the implementation of the "scan" command.
 *
 * 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. */
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    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;
    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;







|







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
    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, 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
	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.
	     */


	    value = strtoul(format-1, &end, 10);	/* INTL: "C" locale. */
	    if (*end != '$') {
		goto notXpg;
	    }
	    format = end+1;
	    format += TclUtfToUniChar(format, &ch);
	    gotXpg = 1;
	    if (gotSequential) {
		goto mixedXPG;
	    }




	    objIndex = value - 1;
	    if ((objIndex < 0) || (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.
		 */
		xpgSize = (xpgSize > value) ? xpgSize : value;
	    }
	    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);
	    goto error;
	}

    xpgCheckDone:
	/*
	 * Parse any width specifier.
	 */

	if ((ch < 0x80) && isdigit(UCHAR(ch))) {	/* INTL: "C" locale. */



	    value = strtoul(format-1, (char **) &format, 10);	/* INTL: "C" locale. */












	    flags |= SCAN_WIDTH;
	    format += TclUtfToUniChar(format, &ch);
	}

	/*
	 * Handle any size specifier.
	 */







>
|









>
>
>
>
|
|





|
|

|











|









>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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
	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 */
	    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 = (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. 'ull' is guaranteed
		 * to be > 0 and < INT_MAX as per checks above.
		 */
		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", (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(
		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", (void *)NULL);
		goto error;
	    }
	    flags |= SCAN_WIDTH;
	    format += TclUtfToUniChar(format, &ch);
	}

	/*
	 * Handle any size specifier.
	 */
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

	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);
		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);
		goto error;
	    }
	    /*
	     * Fall through!
	     */
	case 'd':
	case 'e':







|













|







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

	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", (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", (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
		}
		format += TclUtfToUniChar(format, &ch);
	    }
	    break;
	badSet:
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "unmatched [ in format string", -1));
	    Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BRACKET", 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);
	    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;
		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++) {
		    nassign[i] = 0;
		}
	    }
	    nassign[objIndex]++;
	    objIndex++;
	}
    }







|








|










|







|







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
		}
		format += TclUtfToUniChar(format, &ch);
	    }
	    break;
	badSet:
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "unmatched [ in format string", -1));
	    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", (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.
		 */

		int nspaceOrig = nspace;
		if (xpgSize) {
		    nspace = xpgSize;
		} else {
		    nspace += 16;	/* formerly STATIC_LIST_SIZE */
		}
		nassign = (int *)TclStackRealloc(interp, nassign,
			nspace * sizeof(int));
		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
	*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);
	    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);
	    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);
    } else {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"different numbers of variable names and field specifiers",
		-1));
	Tcl_SetErrorCode(interp, "TCL", "FORMAT", "FIELDVARMISMATCH", NULL);
    }

  error:
    TclStackFree(interp, nassign);
    return TCL_ERROR;
}








|










|











|




|







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
	*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", (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", (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", (char *)NULL);
    } else {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"different numbers of variable names and field specifiers",
		-1));
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ScanObjCmd(
    TCL_UNUSED(ClientData),
    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;
    const char *string, *end, *baseString;
    char op = 0;
    int width, underflow = 0;

    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,







|










|
>







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_ScanObjCmd(
    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;
    const char *string, *end, *baseString;
    char op = 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
	 */

	if (ch == '*') {
	    flags |= SCAN_SUPPRESS;
	    format += TclUtfToUniChar(format, &ch);
	} else if ((ch < 0x80) && isdigit(UCHAR(ch))) {	/* INTL: "C" locale. */
	    char *formatEnd;

	    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. */

	    width = (int) strtoul(format-1, (char **) &format, 10);/* INTL: "C" locale. */


	    format += TclUtfToUniChar(format, &ch);
	} else {
	    width = 0;
	}

	/*
	 * Handle any size specifier.







>













>
|
>
>







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
	 */

	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;
	    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
	    break;
	}
	case 'c':
	    /*
	     * Scan a single Unicode character.
	     */

	    offset = TclUtfToUCS4(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)) {
		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) {
		    wideValue = WIDE_MAX;
		    if (TclGetString(objPtr)[0] == '-') {
			wideValue = WIDE_MIN;


		    }
		}
		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);
			return TCL_ERROR;
		    } else {
			Tcl_SetBignumObj(objPtr, &big);
		    }
		} else {
		    TclSetIntObj(objPtr, wideValue);
		}







|



















|


















|
<


>
>







|







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
	    break;
	}
	case 'c':
	    /*
	     * Scan a single Unicode character.
	     */

	    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)) {
		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 (TclGetWideIntFromObj(NULL, objPtr, &wideValue) != TCL_OK) {

		    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", (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
			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);
			return TCL_ERROR;
		    }
		}
	    } else {
		if (TclGetLongFromObj(NULL, objPtr, &value) != TCL_OK) {
		    if (TclGetString(objPtr)[0] == '-') {
			value = LONG_MIN;
		    } else {
			value = LONG_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);
			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);
	    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);







|

















|



















|







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
			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", (char *)NULL);
			return TCL_ERROR;
		    }
		}
	    } else {
		if (TclGetLongFromObj(NULL, objPtr, &value) != TCL_OK) {
		    if (TclGetString(objPtr)[0] == '-') {
			value = LONG_MIN;
		    } else {
			value = LONG_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", (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
	     */

	    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
	    } 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);
		    if (irPtr) {
			dvalue = irPtr->doubleValue;
		    } else
#endif
		    {
			Tcl_DecrRefCount(objPtr);
			goto done;







|
|







1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
	    } 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_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
		code = TCL_ERROR;
	    }
	    Tcl_DecrRefCount(objs[i]);
	}
    } else {
	/*
	 * Here no vars were specified, we want a list returned (inline scan)


	 */



	TclNewObj(objPtr);
	for (i = 0; i < totalVars; i++) {
	    if (objs[i] != NULL) {
		Tcl_ListObjAppendElement(NULL, objPtr, objs[i]);
		Tcl_DecrRefCount(objs[i]);
	    } else {
		/*
		 * More %-specifiers than matching chars, so we just spit out
		 * empty strings for these.
		 */

		Tcl_ListObjAppendElement(NULL, objPtr, Tcl_NewObj());
	    }











	}
    }
    if (objs != NULL) {
	Tcl_Free(objs);
    }
    if (code == TCL_OK) {
	if (underflow && (nconversions == 0)) {
	    if (numVars) {
		TclNewIndexObj(objPtr, TCL_INDEX_NONE);
	    } else {
		if (objPtr) {
		    Tcl_SetListObj(objPtr, 0, NULL);
		} else {
		    TclNewObj(objPtr);
		}
	    }







>
>

|
>
>

|

|







|

>
>
>
>
>
>
>
>
>
>
>








|







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
		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;
	TclNewObj(emptyObj);
	Tcl_IncrRefCount(emptyObj);
	TclNewObj(objPtr);
	for (i = 0; code == TCL_OK && i < totalVars; i++) {
	    if (objs[i] != NULL) {
		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.
		 */

		code = Tcl_ListObjAppendElement(interp, objPtr, emptyObj);
	    }
	}
	Tcl_DecrRefCount(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) {
		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
/*
 * 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]);
	if (lwrv[i] == NULL) {
	    return TCL_ERROR;
	}
	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(
    ClientData clientData, Tcl_Interp *interp,
    int objc, Tcl_Obj *const objv[])
{
    const char *cs, *cin, *ret;
    static const char *const options[] = {
	"index", "puts-index", "findequal",
	NULL
    };
    enum optionInd {
	O_INDEX,  O_PUTS_INDEX, O_FINDEQUAL
    };
    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
/*
 * 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.
 *
 * 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






/*
 * 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.
 */










|













>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * 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 © 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
/*
 * 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__)
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 \
    fpu_control_t roundTo53Bits = FPU_IEEE_ROUNDING;	\
    fpu_control_t oldRoundingMode;			\

    _FPU_GETCW(oldRoundingMode);			\
    _FPU_SETCW(roundTo53Bits)
#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 \
    ieee_flags("set","precision","double",NULL)
#define TCL_DEFAULT_DOUBLE_ROUNDING \
    ieee_flags("clear","precision",NULL,NULL)



/*
 * 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.
 */

#else /* !__GNUC__ && !__sun */
#define TCL_IEEE_DOUBLE_ROUNDING	((void) 0)
#define TCL_DEFAULT_DOUBLE_ROUNDING	((void) 0)
#endif
#else /* !__i386 */
#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.
 */








<
|


|
|
|
|
|

|
>


|





|
|
>
|

|


>
>




|
<
|
<
<
<
|
|







45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

86



87
88
89
90
91
92
93
94
95
/*
 * 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__)
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_DECL \
    fpu_control_t roundTo53Bits = FPU_IEEE_ROUNDING;	\
    fpu_control_t oldRoundingMode;
#  define TCL_IEEE_DOUBLE_ROUNDING \
    _FPU_GETCW(oldRoundingMode);			\
    _FPU_SETCW(roundTo53Bits)
#  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_DECL
#  define TCL_IEEE_DOUBLE_ROUNDING \
    ieee_flags("set","precision","double",NULL)
#  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) */

#  define TCL_IEEE_DOUBLE_ROUNDING_DECL



#  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.
 */

253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
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 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 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 **);







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|


















|







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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[] = {
    (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 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 **);
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
 *	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.
 *
 *	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).







|
|
|







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
 *	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 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
    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
				 * 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,







|







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
    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. */
    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
				 * 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. */
    const char *acceptPoint;	/* Pointer to position after last character in
				 * an acceptable number. */
    size_t 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)

    /*
     * 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)) {
		/* A dict can never be a (single) number */
		return TCL_ERROR;
	    }
	    if (TclHasIntRep(objPtr, &tclListType)) {
		int 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';

















































































	switch (state) {

	case INITIAL:
	    /*
	     * Initial state. Acceptable characters are +, -, digits, period,
	     * I, N, and whitespace.
	     */







|


|






<
<

<
|








|



|
|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
				 * 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. */
    Tcl_Size len;		/* Number of characters remaining after p. */
    const char *acceptPoint;	/* Pointer to position after last character in
				 * an acceptable number. */
    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;




#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 (TclHasInternalRep(objPtr, &tclDictType)) {
		/* A dict can never be a (single) number */
		return TCL_ERROR;
	    }
	    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
	     * 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) {
		    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) {
		    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.
			 */

			if ((octalSignificandWide != 0)
				&& (((size_t)shift >=
					CHAR_BIT*sizeof(Tcl_WideUInt))
				|| (octalSignificandWide >
					((Tcl_WideUInt)-1 >> shift)))) {
			    octalSignificandOverflow = 1;
			    err = mp_init_u64(&octalSignificandBig,
				    octalSignificandWide);
			}
		    }
		    if (!octalSignificandOverflow) {








			octalSignificandWide =

				(octalSignificandWide << shift) + (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'),







|












|









<
<
<




<
<
<




















<



<









|
|
|






|






>
>
>
>
>
>
>
>
|
>
|







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
	     * 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)) {
		    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)) {
		    goto endgame;
		}
		state = ZERO_B;
		break;
	    }
	    if (flags & TCL_PARSE_BINARY_ONLY) {
		goto zerob;
	    }
	    if (c == 'o' || c == 'O') {



		state = ZERO_O;
		break;
	    }
	    if (c == 'd' || c == 'D') {



		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++;

		state = OCTAL;
		break;
	    } else if (c >= '1' && c <= '7') {

		if (objPtr != NULL) {
		    shift = 3 * (numTrailZeros + 1);
		    significandOverflow = AccumulateDecimalDigit(
			    (unsigned)(c-'0'), numTrailZeros,
			    &significandWide, &significandBig,
			    significandOverflow);

		    if (!octalSignificandOverflow) {
			/*
			 * 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 >
					(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 <<= 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
		    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.
		     */

		    if (significandWide != 0 &&
			    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
			    significandWide > ((Tcl_WideUInt)-1 >> shift))) {
			significandOverflow = 1;
			err = mp_init_u64(&significandBig,
				significandWide);
		    }
		}
		if (!significandOverflow) {










		    significandWide = (significandWide << shift) + 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 */
	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.
		     */

		    if (significandWide != 0 &&
			    ((size_t)shift >= CHAR_BIT*sizeof(Tcl_WideUInt) ||
			    significandWide > ((Tcl_WideUInt)-1 >> shift))) {
			significandOverflow = 1;
			err = mp_init_u64(&significandBig,
				significandWide);
		    }
		}
		if (!significandOverflow) {










		    significandWide = (significandWide << shift) + 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







<
<
<
<



















<



<


<


<

<
<
<
<







|
|
|




|






>
>
>
>
>
>
>
>
>
>
|


















|




<


<
<
<
<







|
|
|




|






>
>
>
>
>
>
>
>
>
>
|
















<


<
<
<
<
<


<
















<











<


<
<
<
<



<



<







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
		    numSigDigs += numTrailZeros+1;
		} else {
		    numSigDigs = 1;
		}
		numTrailZeros = 0;
		state = OCTAL;
		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++;

		state = HEXADECIMAL;
		break;
	    } else if (isdigit(UCHAR(c))) {

		d = (c-'0');
	    } else if (c >= 'A' && c <= 'F') {

		d = (c-'A'+10);
	    } else if (c >= 'a' && c <= 'f') {

		d = (c-'a'+10);




	    } else {
		goto endgame;
	    }
	    if (objPtr != NULL) {
		shift = 4 * (numTrailZeros + 1);
		if (!significandOverflow) {
		    /*
		     * 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 > (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 += 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 */
	case ZERO_B:
	zerob:
	    if (c == '0') {
		numTrailZeros++;

		state = BINARY;
		break;




	    } else if (c != '1') {
		goto endgame;
	    }
	    if (objPtr != NULL) {
		shift = numTrailZeros + 1;
		if (!significandOverflow) {
		    /*
		     * 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 > (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 += 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') {

		numTrailZeros++;
	    } else if ( ! isdigit(UCHAR(c))) {





		goto endgame;
	    }

	    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++;

		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;

		state = DECIMAL;
		break;




	    } else if (flags & TCL_PARSE_INTEGER_ONLY) {
		goto endgame;
	    } else if (c == '.') {

		state = FRACTION;
		break;
	    } else if (c == 'E' || c == 'e') {

		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
	    }
	    /* 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;

	}

	p++;
	len--;
    }

  endgame:
    if (acceptState == INITIAL) {
	/*







<
















<


<
<
<
<











<




<













<


<
<
<
<


















<


<
<
<
<










<






<








<







<






<






<






<











<






<









<










<






<














<












|
<
>







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
	    }
	    /* FALLTHROUGH */

	case LEADING_RADIX_POINT:
	    if (c == '0') {
		numDigitsAfterDp++;
		numTrailZeros++;

		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;

		state = FRACTION;
		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 == '+') {

		state = EXPONENT_SIGNUM;
		break;
	    } else if (c == '-') {
		exponentSignum = 1;

		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';

		state = EXPONENT;
		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;
		}

		state = EXPONENT;
		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') {

		state = sIN;
		break;
	    }
	    goto endgame;
	case sIN:
	    if (c == 'f' || c == 'F') {

		state = sINF;
		break;
	    }
	    goto endgame;
	case sINF:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;

	    if (c == 'i' || c == 'I') {
		state = sINFI;
		break;
	    }
	    goto endgame;
	case sINFI:
	    if (c == 'n' || c == 'N') {

		state = sINFIN;
		break;
	    }
	    goto endgame;
	case sINFIN:
	    if (c == 'i' || c == 'I') {

		state = sINFINI;
		break;
	    }
	    goto endgame;
	case sINFINI:
	    if (c == 't' || c == 'T') {

		state = sINFINIT;
		break;
	    }
	    goto endgame;
	case sINFINIT:
	    if (c == 'y' || c == 'Y') {

		state = sINFINITY;
		break;
	    }
	    goto endgame;

	    /*
	     * Parse NaN's.
	     */
#ifdef IEEE_FLOATING_POINT
	case sN:
	    if (c == 'a' || c == 'A') {

		state = sNA;
		break;
	    }
	    goto endgame;
	case sNA:
	    if (c == 'n' || c == 'N') {

		state = sNAN;
		break;
	    }
	    goto endgame;
	case sNAN:
	    acceptState = state;
	    acceptPoint = p;
	    acceptLen = len;
	    if (c == '(') {

		state = sNANPAREN;
		break;
	    }
	    goto endgame;

	    /*
	     * Parse NaN(hexdigits)
	     */
	case sNANHEX:
	    if (c == ')') {

		state = sNANFINISH;
		break;
	    }
	    /* FALLTHROUGH */
	case sNANPAREN:
	    if (TclIsSpaceProcM(c)) {

		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;

		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
    } 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;

	if (!(flags & TCL_PARSE_NO_WHITESPACE)) {
	    /*
	     * Accept trailing whitespace.
	     */

	    while (len != 0 && TclIsSpaceProcM(*p)) {







|
|







1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
    } 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 = 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
    }

    /*
     * Generate and store the appropriate internal rep.
     */

    if (status == TCL_OK && objPtr != NULL) {
	TclFreeIntRep(objPtr);
	switch (acceptState) {
	case SIGNUM:
	case ZERO_X:
	case ZERO_O:
	case ZERO_B:
	case ZERO_D:
	case LEADING_RADIX_POINT:







|







1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
    }

    /*
     * Generate and store the appropriate internal rep.
     */

    if (status == TCL_OK && objPtr != NULL) {
	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
		    ((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) {







		    significandWide <<= shift;

		} else if (err == MP_OKAY) {
		    err = mp_mul_2d(&significandBig, shift, &significandBig);
		}
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }







>
>
>
>
>
>
>
|
>







1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
		    ((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;
		    }
		} 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
		    ((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) {







		    significandWide <<= shift;

		} else if (err == MP_OKAY) {
		    err = mp_mul_2d(&significandBig, shift, &significandBig);
		}
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }







>
>
>
>
>
>
>
|
>







1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
		    ((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;
		    }
		} 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
		    octalSignificandWide > (MOST_BITS + signum) >> shift)) {
		octalSignificandOverflow = 1;
		err = mp_init_u64(&octalSignificandBig,
			octalSignificandWide);
	    }
	    if (shift) {
		if (!octalSignificandOverflow) {







		    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;
		    } else {
			objPtr->internalRep.wideValue =
				(Tcl_WideInt) octalSignificandWide;
		    }
		}
	    }
	    if ((err == MP_OKAY) && octalSignificandOverflow) {
		if (signum) {
		    err = mp_neg(&octalSignificandBig, &octalSignificandBig);
		}
		TclSetBignumIntRep(objPtr, &octalSignificandBig);
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }
	    break;

	case ZERO:







>
>
>
>
>
>
>
|
>














|


|







|







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
		    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;
		    }
		} 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);
		    } else {
			objPtr->internalRep.wideValue =
				(Tcl_WideInt)octalSignificandWide;
		    }
		}
	    }
	    if ((err == MP_OKAY) && octalSignificandOverflow) {
		if (signum) {
		    err = mp_neg(&octalSignificandBig, &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
		    err = mp_init_u64(&significandBig,
			    significandWide);
		    significandOverflow = 1;
		} else {
		    objPtr->typePtr = &tclIntType;
		    if (signum) {
			objPtr->internalRep.wideValue =
				- (Tcl_WideInt) significandWide;
		    } else {
			objPtr->internalRep.wideValue =
				(Tcl_WideInt) significandWide;
		    }
		}
	    }
	    if ((err == MP_OKAY) && significandOverflow) {
		if (signum) {
		    err = mp_neg(&significandBig, &significandBig);
		}
		TclSetBignumIntRep(objPtr, &significandBig);
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }
	    break;

	case FRACTION:







|


|







|







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
		    err = mp_init_u64(&significandBig,
			    significandWide);
		    significandOverflow = 1;
		} else {
		    objPtr->typePtr = &tclIntType;
		    if (signum) {
			objPtr->internalRep.wideValue =
				(Tcl_WideInt)(-significandWide);
		    } else {
			objPtr->internalRep.wideValue =
				(Tcl_WideInt)significandWide;
		    }
		}
	    }
	    if ((err == MP_OKAY) && significandOverflow) {
		if (signum) {
		    err = mp_neg(&significandBig, &significandBig);
		}
		TclSetBignumInternalRep(objPtr, &significandBig);
	    }
	    if (err != MP_OKAY) {
		return TCL_ERROR;
	    }
	    break;

	case FRACTION:
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
	if (interp != NULL) {
	    Tcl_Obj *msg = Tcl_ObjPrintf("expected %s but got \"",
		    expected);

	    Tcl_AppendLimitedToObj(msg, bytes, numBytes, 50, "");
	    Tcl_AppendToObj(msg, "\"", -1);
	    Tcl_SetObjResult(interp, msg);
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", NULL);
	}
    }

    /*
     * Free memory.
     */








|







1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
	if (interp != NULL) {
	    Tcl_Obj *msg = Tcl_ObjPrintf("expected %s but got \"",
		    expected);

	    Tcl_AppendLimitedToObj(msg, bytes, numBytes, 50, "");
	    Tcl_AppendToObj(msg, "\"", -1);
	    Tcl_SetObjResult(interp, msg);
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "NUMBER", (void *)NULL);
	}
    }

    /*
     * Free memory.
     */

1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
	    /*
	     * 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]) {
	    /*
	     * 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;







|







1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
	    /*
	     * There's no need to multiply if the multiplicand is zero.
	     */

	    *wideRepPtr = digit;
	    return 0;
	} else if (numZeros >= maxpow10_wide
		|| 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
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 */
{

    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.

     */

    TCL_IEEE_DOUBLE_ROUNDING;

    /*
     * Test for the easy cases.

     */

    if (significand == 0) {
	return copysign(0.0, -signum);
    }







    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
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
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

    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. We also make
     * 'retval' volatile, so that it doesn't get promoted to a register.
     */
    volatile double retval;		/* Value of the number. */


    /*
     * 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
			((Tcl_WideInt)significand / pow10vals[-exponent]);
		goto returnValue;
	    }
	}
    }

    /*
     * All the easy cases have failed. Promote ths 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,







|







1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
			((Tcl_WideInt)significand / pow10vals[-exponent]);
		goto returnValue;
	    }
	}
    }

    /*
     * 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
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 */
{

    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.


     */

    TCL_IEEE_DOUBLE_ROUNDING;

    /*
     * Quick checks for zero, and over/underflow. Be careful to avoid
     * integer overflow when calculating with 'exponent'.

     */

    if (mp_iszero(significand)) {
	return copysign(0.0, -signum);
    }











    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;
    }







>
|







|
>
>

|
<


<
|
>

<



>
>
>
>
>
>
>
>
>
>
>







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
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

    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. We also make
     * 'retval' volatile to make sure that it doesn't get promoted to a
     * register.
     */
    volatile double retval;


    /*

     * 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
	    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.
     */

    if (mp_init_copy(&twoMd, exactSignificand) != MP_OKAY) {
	mp_clear(&twoMv);
	return approxResult;
    }
    for (i = 0; (i <= 8); ++i) {







|







2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
	    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 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

    /*
     * 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);
	if ((rteSigWide & 1) == 0) {
	    mp_clear(&twoMd);
	    mp_clear(&twoMv);
	    return approxResult;
	}
    }








|







2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157

    /*
     * 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);
	if ((rteSigWide & 1) == 0) {
	    mp_clear(&twoMd);
	    mp_clear(&twoMv);
	    return approxResult;
	}
    }

2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
}

/*
 *----------------------------------------------------------------------
 *
 * RequiredPrecision --
 *
 *	Determines the number of bits needed to hold an intger.
 *
 * Results:
 *	Returns the position of the most significant bit (0 - 63).  Returns 0
 *	if the number is zero.
 *
 *----------------------------------------------------------------------
 */







|







2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
}

/*
 *----------------------------------------------------------------------
 *
 * RequiredPrecision --
 *
 *	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.
 *
 *----------------------------------------------------------------------
 */
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

    if (k_check && d < 1. && ilim > 0) {
	if (ilim1 < 0) {
	    return NULL;
	}
	ilim = ilim1;
	--k;
	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.;
	if (d > eps.d) {
	    *retval = '1';
	    *decpt = k;
	    return retval;
	} else if (d < -eps.d) {
	    *decpt = k;
	    return retval;







|
















|







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

    if (k_check && d < 1. && ilim > 0) {
	if (ilim1 < 0) {
	    return NULL;
	}
	ilim = ilim1;
	--k;
	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 = d - 5.;
	if (d > eps.d) {
	    *retval = '1';
	    *decpt = k;
	    return retval;
	} else if (d < -eps.d) {
	    *decpt = k;
	    return retval;
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
     * 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);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return (err == MP_OKAY) ? retval : NULL;
}







|







3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
     * 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, (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
				 * 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;

}

/*
 *----------------------------------------------------------------------
 *
 * ShouldBankerRoundUpToNext --
 *







<
<




<
<
>
|
>







3806
3807
3808
3809
3810
3811
3812


3813
3814
3815
3816


3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
				 * 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_EQ:
	return isodd;
    case MP_GT:
	return 1;


    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
     */

    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) {
    case MP_LT:
	return 0;
    case MP_EQ:
	return isodd;
    case MP_GT:
	return 1;
    }
    Tcl_Panic("in ShouldBankerRoundUpToNext, trichotomy fails!");

    return 0;

}

/*
 *----------------------------------------------------------------------
 *
 * ShorteningBignumConversion --
 *







|
<
<




<
<
>
|
>







3849
3850
3851
3852
3853
3854
3855
3856


3857
3858
3859
3860


3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
     */

    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) {


    case MP_EQ:
	return isodd;
    case MP_GT:
	return 1;


    default:
	return 0;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * ShorteningBignumConversion --
 *
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
     * 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);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}







|







4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
     * 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, (void *)NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
    ++s;

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    mp_clear_multi(&b, &S, &dig, NULL);
    *s = '\0';
    *decpt = k;
    if (endPtr) {
	*endPtr = s;
    }
    return retval;
}







|







4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
    ++s;

    /*
     * Endgame - store the location of the decimal point and the end of the
     * string.
     */

    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
	m2plus = m2minus;
	if (!denorm && bw == 1) {
	    ++b2;
	    ++s2;
	    ++m2plus;
	}

	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]).
	     */







|







4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
	m2plus = m2minus;
	if (!denorm && bw == 1) {
	    ++b2;
	    ++s2;
	    ++m2plus;
	}

	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

	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 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.
	     */








|







4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559

	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 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
    mp_err err;
    mp_int *b = (mp_int *)big;

    /*
     * Infinite values can't convert to bignum.
     */

    if (TclIsInfinite(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);
	}
	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);
	int shift = expt - mantBits;

	err = mp_init_i64(b, w);
	if (err != MP_OKAY) {
		/* just skip */
	} else if (shift < 0) {
	    err = mp_div_2d(b, -shift, b, NULL);







|




|









|







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
    mp_err err;
    mp_int *b = (mp_int *)big;

    /*
     * Infinite values can't convert to bignum.
     */

    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, (void *)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);
	int shift = expt - mantBits;

	err = mp_init_i64(b, w);
	if (err != MP_OKAY) {
		/* just skip */
	} else if (shift < 0) {
	    err = mp_div_2d(b, -shift, b, NULL);
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
{
#ifndef IEEE_FLOATING_POINT
    strcpy(buffer, "NaN");
    return;
#else
    union {
	double dv;
	Tcl_WideUInt 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);
	*buffer++ = '-';
    }
    *buffer++ = 'N';
    *buffer++ = 'a';
    *buffer++ = 'N';
    bitwhack.iv &= (((Tcl_WideUInt) 1) << 51) - 1;
    if (bitwhack.iv != 0) {
	sprintf(buffer, "(%" TCL_LL_MODIFIER "x)", bitwhack.iv);
    } else {
	*buffer = '\0';
    }
#endif /* IEEE_FLOATING_POINT */
}

/*







|






|
|





|

|







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
{
#ifndef IEEE_FLOATING_POINT
    strcpy(buffer, "NaN");
    return;
#else
    union {
	double dv;
	uint64_t iv;
    } bitwhack;

    bitwhack.dv = value;
    if (n770_fp) {
	bitwhack.iv = Nokia770Twiddle(bitwhack.iv);
    }
    if (bitwhack.iv & (UINT64_C(1) << 63)) {
	bitwhack.iv &= ~ (UINT64_C(1) << 63);
	*buffer++ = '-';
    }
    *buffer++ = 'N';
    *buffer++ = 'a';
    *buffer++ = 'N';
    bitwhack.iv &= ((UINT64_C(1)) << 51) - 1;
    if (bitwhack.iv != 0) {
	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
/*
 * 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.
 *
 *	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
 *	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
 *	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
 *	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.
 */

#include "tclInt.h"
#include "tclTomMath.h"
#include "tclStringRep.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);
static void		AppendUnicodeToUtfRep(Tcl_Obj *objPtr,
			    const Tcl_UniChar *unicode, size_t numChars);
static void		AppendUtfToUnicodeRep(Tcl_Obj *objPtr,
			    const char *bytes, size_t numBytes);
static void		AppendUtfToUtfRep(Tcl_Obj *objPtr,
			    const char *bytes, size_t 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 void		ExtendUnicodeRepWithString(Tcl_Obj *objPtr,
			    const char *bytes, size_t numBytes,
			    size_t 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 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);
static void		UpdateStringOfString(Tcl_Obj *objPtr);




/*
 * 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 */

};

/*
 * TCL STRING GROWTH ALGORITHM
 *
 * When growing strings (during an append, for example), the following growth
 * algorithm is used:



|
|
|
|

|
|
|
<
<
>
|

|
|

|
|
|
|


<
|



|
|








<
|







|

|

|

|


|
|

|
|


|
|


|
|

>
>
>











|
>







1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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-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.
 *
 * 	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.


 *
 *	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 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-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 space, we allocate double the space and use the
 *	internal representation to keep track of how much space is used vs.
 *	allocated.
 *
 * 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>
/*
 * 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, Tcl_Size appendNumChars);
static void		AppendUnicodeToUtfRep(Tcl_Obj *objPtr,
			    const Tcl_UniChar *unicode, Tcl_Size numChars);
static void		AppendUtfToUnicodeRep(Tcl_Obj *objPtr,
			    const char *bytes, Tcl_Size numBytes);
static void		AppendUtfToUtfRep(Tcl_Obj *objPtr,
			    const char *bytes, Tcl_Size numBytes);
static void		DupStringInternalRep(Tcl_Obj *objPtr,
			    Tcl_Obj *copyPtr);
static Tcl_Size		ExtendStringRepWithUnicode(Tcl_Obj *objPtr,
			    const Tcl_UniChar *unicode, Tcl_Size numChars);
static void		ExtendUnicodeRepWithString(Tcl_Obj *objPtr,
			    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, 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, 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 */
    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
#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)
{
    /*
     * Pre-conditions:
     *	objPtr->typePtr == &tclStringType
     *	needed > stringPtr->allocated
     *	flag || objPtr->bytes != NULL
     */

    String *stringPtr = GET_STRING(objPtr);
    char *ptr = NULL;

    size_t attempt;



    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;
	    size_t extra = needed - objPtr->length + TCL_MIN_GROWTH;
	    size_t growth = (extra > limit) ? limit : extra;

	    attempt = needed + growth;

	    ptr = (char *)Tcl_AttemptRealloc(objPtr->bytes, attempt + 1);
	}
    }
    if (ptr == NULL) {
	/*
	 * 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;
}

static void
GrowUnicodeBuffer(
    Tcl_Obj *objPtr,
    size_t needed)
{
    /*
     * Pre-conditions:
     *	objPtr->typePtr == &tclStringType
     *	needed > stringPtr->maxChars
     */

    String *ptr = NULL, *stringPtr = GET_STRING(objPtr);
    size_t attempt;

    if (stringPtr->maxChars > 0) {
	/*
	 * Subsequent appends - apply the growth algorithm.
	 */

	attempt = 2 * needed;
	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_MIN_UNICHAR_GROWTH;


	    attempt = needed + extra;
	    ptr = stringAttemptRealloc(stringPtr, attempt);


	}
    }
    if (ptr == NULL) {
	/*
	 * First allocation - just big enough; or last chance fallback.

	 */

	attempt = needed;
	ptr = stringRealloc(stringPtr, attempt);
    }
    stringPtr = ptr;
    stringPtr->maxChars = attempt;
    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
 *	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"
				 * when initializing the new object. If
				 * negative, 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"
				 * when initializing the new object. If -1,
				 * use bytes up to the first NUL byte. */
{
    Tcl_Obj *objPtr;

    if (length == TCL_INDEX_NONE) {
	length = (bytes? strlen(bytes) : 0);
    }
    TclNewStringObj(objPtr, bytes, length);
    return objPtr;
}
#endif /* TCL_MEM_DEBUG */








|
|


|
|





|
>
|
>
>




<
<
<
<
|
<
<
>
>
|
|
|
<
<
|
<
>
|
<
<
|
<
<
<
|
<
<
|

|





|


|
|



|
|

<
<
<
<
|
|
<
<
<
<
<
<
>
>
|
|
<
|
>
|
<
>
>
|
<
<

|
>

|
|
<

<
|




















|













|

|









|





|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146




147


148
149
150
151
152


153

154
155


156



157


158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176




177
178






179
180
181
182

183
184
185

186
187
188


189
190
191
192
193
194

195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
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,
    Tcl_Size needed, /* Not including terminating nul */
    int flag)      /* If 0, try to overallocate */
{
    /*
     * Preconditions:
     *	TclHasInternalRep(objPtr, &tclStringType)
     *	needed > stringPtr->allocated
     *	flag || objPtr->bytes != NULL
     */

    String *stringPtr = GET_STRING(objPtr);
    char *ptr;
    Tcl_Size capacity;

    assert(needed <= TCL_SIZE_MAX - 1);
    needed += 1; /* Include terminating nul */

    if (objPtr->bytes == &tclEmptyString) {
	objPtr->bytes = NULL;
    }




    /*


     * 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);


    } else {

	/* Allocate exact size */
	ptr = (char *)Tcl_Realloc(objPtr->bytes, needed);


	capacity = needed;



    }



    objPtr->bytes = ptr;
    stringPtr->allocated = capacity - 1; /* Does not include slot for end nul */
}

static void
GrowUnicodeBuffer(
    Tcl_Obj *objPtr,
    Tcl_Size needed)
{
    /*
     * Preconditions:
     *	TclHasInternalRep(objPtr, &tclStringType)
     *	needed > stringPtr->maxChars
     */

    String *stringPtr = GET_STRING(objPtr);
    Tcl_Size maxChars;





    /* Note STRING_MAXCHARS already takes into account space for nul */
    if (needed > STRING_MAXCHARS) {






	Tcl_Panic("max size for a Tcl unicode rep (%" TCL_Z_MODIFIER "d bytes) exceeded",
		  STRING_MAXCHARS);
    }
    if (stringPtr->maxChars > 0) {

	/* Expansion - try allocating extra space */
	stringPtr = (String *) TclReallocElemsEx(stringPtr,
		needed + 1, /* +1 for nul */

		sizeof(Tcl_UniChar), offsetof(String, unicode), &maxChars);
	maxChars -= 1; /* End nul not included */
    } else {


	/*
	 * First allocation - just big enough. Note needed does
	 * not include terminating nul but STRING_SIZE does
	 */
	stringPtr = (String *)Tcl_Realloc(stringPtr, STRING_SIZE(needed));
	maxChars = needed;

    }

    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 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. */
    Tcl_Size length)		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If
				 * TCL_INDEX_NONE, use bytes up to the first NUL
				 * byte. */
{
    return Tcl_DbNewStringObj(bytes, length, "unknown", 0);
}
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_NewStringObj(
    const char *bytes,		/* Points to the first of the length bytes
				 * used to initialize the new object. */
    Tcl_Size length)		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If -1,
				 * use bytes up to the first NUL byte. */
{
    Tcl_Obj *objPtr;

    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
 *	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
 *	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"
				 * 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. */
{







|












|







271
272
273
274
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 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. */
    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
    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"
				 * 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);
}







|







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. */
    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
 *---------------------------------------------------------------------------
 */

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
				 * 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.
 *
 * Side effects:
 *	Frees old internal rep. Allocates memory for new "String" internal
 *	rep.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_GetCharLength(
    Tcl_Obj *objPtr)		/* The String object to get the num chars
				 * of. */
{
    String *stringPtr;
    size_t numChars = 0;




















































    /*
     * Quick, no-shimmer return for short string reps.
     */

    if ((objPtr->bytes) && (objPtr->length < 2)) {
	/* 0 bytes -> 0 chars; 1 byte -> 1 char */







|

















|








|





|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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. */
    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.
 *
 * Side effects:
 *	Frees old internal rep. Allocates memory for new "String" internal
 *	rep.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_GetCharLength(
    Tcl_Obj *objPtr)		/* The String object to get the num chars
				 * of. */
{
    String *stringPtr;
    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
     * 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;
    }

    /*
     * 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 == 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;

    if (objPtr->bytes == &tclEmptyString) {
	return TCL_EMPTYSTRING_YES;
    }






    if (TclListObjIsCanonical(objPtr)) {
	Tcl_ListObjLength(NULL, objPtr, &length);
	return length == 0;
    }

    if (TclIsPureDict(objPtr)) {
	Tcl_DictObjSize(NULL, objPtr, &length);
	return length == 0;
    }







<
<
<
|
<
<
<
|
<
|
|
|
<
<
<

<
<
|
|
<
|
|




















|





>
>
>
>
>

|







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
     * 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);



    } else {

	TclGetString(objPtr);
	numChars = TclNumUtfChars(objPtr->bytes, objPtr->length);
    }






    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)
{
    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)) {
	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
 *----------------------------------------------------------------------
 */

int
Tcl_GetUniChar(
    Tcl_Obj *objPtr,		/* The object to get the Unicode charater
				 * from. */
    size_t index)		/* Get the index'th Unicode character. */
{
    String *stringPtr;
    int ch;





    /*
     * 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);
	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);
	}



	if (stringPtr->numChars == objPtr->length) {
	    return (Tcl_UniChar) objPtr->bytes[index];
	}
	FillUnicodeRep(objPtr);
	stringPtr = GET_STRING(objPtr);
    }

    if (index >= stringPtr->numChars) {
	return -1;
    }
    ch = stringPtr->unicode[index];


#if TCL_UTF_MAX <= 3



    /* See: bug [11ae2be95dac9417] */


    if ((ch & 0xF800) == 0xD800) {
	if (ch & 0x400) {
	    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 ch;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetUnicodeFromObj --
 *
 *	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.
 *
 *----------------------------------------------------------------------
 */



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
				 * rep's unichar length should be stored. If
				 * NULL, no length is stored. */
{
    String *stringPtr;

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);







|




>
>
>
>

|




|
|




















|

>
>
>

|









>
>
|
>
>
>
|
>
>
|
|
|
<
|
|
|
>
>
|
>
|
>
>
>
>
>
>
|
|
|
|
>
|
>
>
>
>
>






|















>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|







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
 *----------------------------------------------------------------------
 */

int
Tcl_GetUniChar(
    Tcl_Obj *objPtr,		/* The object to get the Unicode charater
				 * from. */
    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
     * we don't 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];
    }

    /*
     * 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) {
	    TclNumUtfCharsM(stringPtr->numChars, objPtr->bytes, objPtr->length);
	}
	if (index >= stringPtr->numChars) {
	    return -1;
	}
	if (stringPtr->numChars == objPtr->length) {
	    return (unsigned char) objPtr->bytes[index];
	}
	FillUnicodeRep(objPtr);
	stringPtr = GET_STRING(objPtr);
    }

    if (index >= stringPtr->numChars) {
	return -1;
    }
    ch = stringPtr->unicode[index];
    return ch;
}

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) {

	return -1;
    }

    /*
	 * Optimize the ByteArray case:  N need 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/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. */
    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
/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * 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_Obj *newObjPtr;		/* The Tcl object to find the range of. */
    String *stringPtr;
    size_t length = 0;

    if (first == TCL_INDEX_NONE) {
	first = TCL_INDEX_START;
    }
    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);

	if (last >= length) {
	    last = length - 1;
	}
	if (last < first) {

	    return Tcl_NewObj();
	}
	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);
	}
	if (stringPtr->numChars == objPtr->length) {
	    if (last >= stringPtr->numChars) {
		last = stringPtr->numChars - 1;
	    }
	    if (last < first) {

		return Tcl_NewObj();
	    }
	    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 < first) {



	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;
    }
#endif





    return Tcl_NewUnicodeObj(stringPtr->unicode + first, last - first + 1);
}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	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"
				 * 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);

    /*
     * 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
 *	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
 *	original string representation are undefined. The object's internal

 *	representation is changed to "expendable string".
 *
 *----------------------------------------------------------------------
 */

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
				 * representation of object, not including
				 * terminating null byte. */
{
    String *stringPtr;





    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetObjLength");
    }

    if (objPtr->bytes && objPtr->length == length) {
	return;
    }







|
>
|













|
|



|

|
|
<
<
<








|

|



>
|

















|


|



>
|

|













|
|


>
>
>
|
|
|
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
|
>
>
|
|
>
>
>
>
>
|
>
|
>
|

|
>
>
>
>
>
|















|












|











|


















|
<





|
|
|
|
|
<
>
|








|





>
>
>
>







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
/*
 *----------------------------------------------------------------------
 *
 * 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.  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. */
    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;
    Tcl_Size length = 0;

    if (first < 0) {
	first = 0;



    }

    /*
     * 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);
    }

    /*
     * 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) {
	    TclNumUtfCharsM(stringPtr->numChars, objPtr->bytes, objPtr->length);
	}
	if (stringPtr->numChars == objPtr->length) {
	    if (last < 0 || last >= stringPtr->numChars) {
		last = stringPtr->numChars - 1;
	    }
	    if (last < first) {
		TclNewObj(newObjPtr);
		return newObjPtr;
	    }
	    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 < 0 || last >= stringPtr->numChars) {
	last = stringPtr->numChars - 1;
    }
    if (last < first) {
	TclNewObj(newObjPtr);
	return newObjPtr;
    }
    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;
    }
    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 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. */
    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.
     */

    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 --
 *
 *	Changes the length of the string representation of objPtr.

 *
 * Results:
 *	None.
 *
 * Side effects:
 *	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.

 *
 *	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. */
    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
	    stringPtr->allocated = length;
	}

	objPtr->length = length;
	objPtr->bytes[length] = 0;

	/*
	 * 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
	 */

	stringPtr->numChars = length;
	stringPtr->unicode[length] = 0;
	stringPtr->hasUnicode = 1;

	/*







|












|







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
	    stringPtr->allocated = length;
	}

	objPtr->length = length;
	objPtr->bytes[length] = 0;

	/*
	 * 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
	 */

	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
 *----------------------------------------------------------------------
 */

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
				 * representation of object, not including
				 * terminating null byte. */
{
    String *stringPtr;






    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_AttemptSetObjLength");
    }
    if (objPtr->bytes && objPtr->length == length) {
	return 1;
    }







|




>
>
>
>
>







1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
 *----------------------------------------------------------------------
 */

int
Tcl_AttemptSetObjLength(
    Tcl_Obj *objPtr,		/* Pointer to object. This object must not
				 * currently be shared. */
    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
	    /*
	     * Need to enlarge the buffer.
	     */

	    char *newBytes;

	    if (objPtr->bytes == &tclEmptyString) {
		newBytes = (char *)Tcl_AttemptAlloc(length + 1);
	    } else {
		newBytes = (char *)Tcl_AttemptRealloc(objPtr->bytes, length + 1);
	    }
	    if (newBytes == NULL) {
		return 0;
	    }
	    objPtr->bytes = newBytes;
	    stringPtr->allocated = length;
	}

	objPtr->length = length;
	objPtr->bytes[length] = 0;

	/*
	 * Invalidate the unicode data.
	 */

	stringPtr->numChars = TCL_INDEX_NONE;
	stringPtr->hasUnicode = 0;
    } else {
	/*
	 * 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.
	 */

	stringPtr->unicode[length] = 0;
	stringPtr->numChars = length;
	stringPtr->hasUnicode = 1;

	/*







|

|












|






|












|







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
	    /*
	     * Need to enlarge the buffer.
	     */

	    char *newBytes;

	    if (objPtr->bytes == &tclEmptyString) {
		newBytes = (char *)Tcl_AttemptAlloc(length + 1U);
	    } else {
		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.
	 */

	stringPtr->numChars = TCL_INDEX_NONE;
	stringPtr->hasUnicode = 0;
    } else {
	/*
	 * 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.
	 */

	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
 *
 *---------------------------------------------------------------------------
 */

void
Tcl_SetUnicodeObj(
    Tcl_Obj *objPtr,		/* The object to set the string of. */
    const Tcl_UniChar *unicode,	/* The unicode string used to initialize the
				 * object. */
    size_t numChars)		/* Number of characters in the unicode
				 * string. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetUnicodeObj");
    }
    TclFreeIntRep(objPtr);
    SetUnicodeObj(objPtr, unicode, numChars);
}

static size_t
UnicodeLength(
    const Tcl_UniChar *unicode)
{
    size_t numChars = 0;

    if (unicode) {

	while ((numChars != TCL_INDEX_NONE) && (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
				 * object. */
    size_t numChars)		/* Number of characters in the unicode
				 * string. */
{
    String *stringPtr;

    if (numChars == TCL_INDEX_NONE) {
	numChars = UnicodeLength(unicode);
    }

    /*
     * Allocate enough space for the String structure + Unicode string.
     */








|

|





|



|



|


>
|









|

|




|







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
 *
 *---------------------------------------------------------------------------
 */

void
Tcl_SetUnicodeObj(
    Tcl_Obj *objPtr,		/* The object to set the string of. */
    const Tcl_UniChar *unicode,	/* The Unicode string used to initialize the
				 * object. */
    Tcl_Size numChars)		/* Number of characters in the Unicode
				 * string. */
{
    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_SetUnicodeObj");
    }
    TclFreeInternalRep(objPtr);
    SetUnicodeObj(objPtr, unicode, numChars);
}

static Tcl_Size
UnicodeLength(
    const Tcl_UniChar *unicode)
{
    Tcl_Size numChars = 0;

    if (unicode) {
	/* TODO - is this overflow check really necessary? */
	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
				 * object. */
    Tcl_Size numChars)		/* Number of characters in the Unicode
				 * string. */
{
    String *stringPtr;

    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
 */

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
				 * 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
				 * 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;

    if (length == TCL_INDEX_NONE) {
	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;
	}

	toCopy = TclUtfPrev(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 (stringPtr->hasUnicode && (stringPtr->numChars+1) > 1) {
	AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
    } else {
	AppendUtfToUtfRep(objPtr, bytes, toCopy);
    }

    if (length <= limit) {
	return;
    }

    stringPtr = GET_STRING(objPtr);
    if (stringPtr->hasUnicode && (stringPtr->numChars+1) > 1) {
	AppendUtfToUnicodeRep(objPtr, ellipsis, eLen);
    } else {
	AppendUtfToUtfRep(objPtr, ellipsis, eLen);
    }
}

/*







|


|






|
|

|

















|


|















>
>
>
>
>
>
|










|







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
 */

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. */
    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. */
    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;
    Tcl_Size toCopy = 0;
    Tcl_Size eLen = 0;

    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 = Tcl_UtfPrev(ellipsis+eLen, ellipsis) - ellipsis;
	}

	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 > 0)) {
	AppendUtfToUnicodeRep(objPtr, bytes, toCopy);
    } else {
	AppendUtfToUtfRep(objPtr, bytes, toCopy);
    }

    if (length <= limit) {
	return;
    }

    stringPtr = GET_STRING(objPtr);
    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
 */

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
				 * byte. */
{
    Tcl_AppendLimitedToObj(objPtr, bytes, length, TCL_INDEX_NONE, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclAppendUnicodeToObj --
 *
 *	This function appends a Unicode string to an object in the most
 *	efficient manner possible. Length must be >= 0.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Invalidates the string rep and creates a new Unicode string.
 *
 *----------------------------------------------------------------------
 */

void
TclAppendUnicodeToObj(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const Tcl_UniChar *unicode,	/* The unicode string to append to the
				 * object. */
    size_t length)		/* Number of chars in "unicode". */

{
    String *stringPtr;

    if (Tcl_IsShared(objPtr)) {
	Tcl_Panic("%s called with shared object", "TclAppendUnicodeToObj");
    }

    if (length == 0) {
	return;
    }

    SetStringFromAny(NULL, objPtr);







|
|


|





|


|











|

|

|
>




|







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
 */

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. */
    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_SIZE_MAX, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AppendUnicodeToObj --
 *
 *	This function appends a Unicode string to an object in the most
 *	efficient manner possible.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Invalidates the string rep and creates a new Unicode string.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_AppendUnicodeToObj(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const Tcl_UniChar *unicode,	/* The Unicode string to append to the
				 * object. */
    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", "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

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;
    const char *bytes;

    /*

     * Special case: second object is standard-empty is fast case. We know
     * that appending nothing to anything leaves that starting anything...
     */

    if (appendObjPtr->bytes == &tclEmptyString) {


	return;
    }



    /*
     * Handle append of one bytearray object to another as a special case.
     * Note that we only do this when the objects are pure so that the
     * bytearray faithfully represent the true value; Otherwise appending the
     * byte arrays together could lose information;
     */

    if ((TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)
	    && TclIsPureByteArray(appendObjPtr)) {
	/*
	 * You might expect the code here to be
	 *
	 *  bytes = TclGetByteArrayFromObj(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;

	(void) TclGetByteArrayFromObj(objPtr, &length);
	(void) TclGetByteArrayFromObj(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);
	return;
    }

    /*
     * Must append as strings.
     */

    SetStringFromAny(NULL, 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)) {
	    Tcl_UniChar *unicode =
		    TclGetUnicodeFromObj(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)) {
	String *appendStringPtr = GET_STRING(appendObjPtr);

	appendNumChars = appendStringPtr->numChars;
    }

    AppendUtfToUtfRep(objPtr, bytes, length);

    if ((numChars != TCL_INDEX_NONE) && (appendNumChars != TCL_INDEX_NONE)) {
	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.
 *
 * 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. */
{
    String *stringPtr;
    size_t numChars;

    if (appendNumChars == TCL_INDEX_NONE) {
	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
     * 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;

	/*
	 * 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;
	}

	GrowUnicodeBuffer(objPtr, numChars);
	stringPtr = GET_STRING(objPtr);

	/*
	 * Relocate unicode if needed; see above.
	 */

	if (index != TCL_INDEX_NONE) {
	    unicode = stringPtr->unicode + index;
	}
    }

    /*
     * Copy the new string onto the end of the old string, then add the
     * trailing null.
     */







|
|


<
>
|
<
<
|
|
>
>



>
>
|
|
<
|
<
|

<
<

|

|















|

|
|



















|










>
>
>
>
>
>
>










|

|


















|







|









|
|














|


|

|










|









|


|






|






|


|
|







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

void
Tcl_AppendObjToObj(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    Tcl_Obj *appendObjPtr)	/* Object to append. */
{
    String *stringPtr;
    Tcl_Size length = 0, numChars;
    Tcl_Size appendNumChars = TCL_INDEX_NONE;
    const char *bytes;


    if (TclCheckEmptyString(appendObjPtr) == TCL_EMPTYSTRING_YES) {
	return;


    }

    if (TclCheckEmptyString(objPtr) == TCL_EMPTYSTRING_YES) {
	TclSetDuplicateObj(objPtr, appendObjPtr);
	return;
    }

    if (TclIsPureByteArray(appendObjPtr)
	    && (TclIsPureByteArray(objPtr) || objPtr->bytes == &tclEmptyString)) {
	/*
	 * Both bytearray objects are pure, so the second internal bytearray value

	 * can be appended to the first, with no need to modify the "bytes" field.

	 */



	/*
	 * One might expect the code here to be
	 *
	 *  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.
	 */

	Tcl_Size lengthSrc = 0;

	(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_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 (TclHasInternalRep(appendObjPtr, &tclStringType)) {
	    Tcl_UniChar *unicode =
		    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 >= 0) && TclHasInternalRep(appendObjPtr, &tclStringType)) {
	String *appendStringPtr = GET_STRING(appendObjPtr);

	appendNumChars = appendStringPtr->numChars;
    }

    AppendUtfToUtfRep(objPtr, bytes, length);

    if ((numChars >= 0) && (appendNumChars >= 0)) {
	stringPtr->numChars = numChars + appendNumChars;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * AppendUnicodeToUnicodeRep --
 *
 *	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. */
    Tcl_Size appendNumChars)	/* Number of chars of "unicode" to append. */
{
    String *stringPtr;
    Tcl_Size numChars;

    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
     * 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) {
	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 (unicode && unicode >= stringPtr->unicode
		&& unicode <= stringPtr->unicode + stringPtr->maxChars) {
	    offset = unicode - stringPtr->unicode;
	}

	GrowUnicodeBuffer(objPtr, numChars);
	stringPtr = GET_STRING(objPtr);

	/*
	 * Relocate Unicode if needed; see above.
	 */

	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
 *----------------------------------------------------------------------
 */

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. */
{
    String *stringPtr = GET_STRING(objPtr);

    numChars = ExtendStringRepWithUnicode(objPtr, unicode, numChars);

    if (stringPtr->numChars != TCL_INDEX_NONE) {
	stringPtr->numChars += numChars;







|







1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
 *----------------------------------------------------------------------
 */

static void
AppendUnicodeToUtfRep(
    Tcl_Obj *objPtr,		/* Points to the object to append to. */
    const Tcl_UniChar *unicode,	/* String to convert to UTF. */
    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
 *	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.
 *
 *----------------------------------------------------------------------
 */

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. */
{
    String *stringPtr;

    if (numBytes == 0) {
	return;
    }








|








|







1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
 *	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 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. */
    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
 *	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.
 *
 *----------------------------------------------------------------------
 */

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. */
{
    String *stringPtr;
    size_t 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;



    newLength = numBytes + oldLength;

    stringPtr = GET_STRING(objPtr);
    if (newLength > stringPtr->allocated) {
	size_t offset = TCL_INDEX_NONE;

	/*
	 * 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) {
	    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) {
	    bytes = objPtr->bytes + offset;
	}
    }

    /*
     * Invalidate the unicode data.
     */

    stringPtr->numChars = TCL_INDEX_NONE;
    stringPtr->hasUnicode = 0;

    if (bytes) {
	memmove(objPtr->bytes + oldLength, bytes, numBytes);
    }
    objPtr->bytes[newLength] = 0;
    objPtr->length = newLength;
}


































/*
 *----------------------------------------------------------------------
 *
 * Tcl_AppendStringsToObj --
 *
 *	This function appends one or more null-terminated strings to an







|








|


|














>
>
>




|







|
|














|








|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	rep of "objPtr". objPtr must already have a valid String rep.
 *	numBytes must be non-negative.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	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. */
    Tcl_Size numBytes)		/* Number of bytes of "bytes" to append. */
{
    String *stringPtr;
    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) {
	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 && 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 >= 0) {
	    bytes = objPtr->bytes + offset;
	}
    }

    /*
     * Invalidate the unicode data.
     */

    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
 */

int
Tcl_AppendFormatToObj(
    Tcl_Interp *interp,
    Tcl_Obj *appendObj,
    const char *format,
    int objc,
    Tcl_Obj *const objv[])
{
    const char *span = format, *msg, *errCode;
    int objIndex = 0, gotXpg = 0, gotSequential = 0;
    size_t 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;

    /*
     * 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 useWide = 0;
#endif
	int newXpg, numChars, allocSegment = 0, segmentLimit;
	size_t segmentNumBytes;
	Tcl_Obj *segment;
	int step = TclUtfToUniChar(format, &ch);

	format += step;
	if (ch != '%') {
	    numBytes += step;
	    continue;







|



|
|













|








|
>



|
|







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
 */

int
Tcl_AppendFormatToObj(
    Tcl_Interp *interp,
    Tcl_Obj *appendObj,
    const char *format,
    Tcl_Size objc,
    Tcl_Obj *const objv[])
{
    const char *span = format, *msg, *errCode;
    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 = 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 gotPrecision, sawFlag, useShort = 0, useBig = 0;
	Tcl_WideInt width, precision;
#ifndef TCL_WIDE_INT_IS_LONG
	int useWide = 0;
#endif
	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

	/*
	 * Step 3. Minimum field width.
	 */

	width = 0;
	if (isdigit(UCHAR(ch))) {


	    width = strtoul(format, &end, 10);

	    if (width < 0) {
		msg = overflow;
		errCode = "OVERFLOW";
		goto errorMsg;
	    }

	    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) {
		goto error;
	    }
	    if (width < 0) {
		width = -width;
		gotMinus = 1;
	    }
	    objIndex++;
	    format += step;
	    step = TclUtfToUniChar(format, &ch);
	}
	if (width > (int) 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))) {


	    precision = strtoul(format, &end, 10);







	    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)
		    != TCL_OK) {
		goto error;
	    }

	    /*
	     * TODO: Check this truncation logic.
	     */







>
>
|
>
|




>








|










|
















>
>
|
>
>
>
>
>
>
>








|







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

	/*
	 * 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;
	    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 (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 > 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;
	    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 (TclGetWideIntFromObj(interp, objv[objIndex], &precision)
		    != TCL_OK) {
		goto error;
	    }

	    /*
	     * TODO: Check this truncation logic.
	     */
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
	    msg = "format string ended in middle of field specifier";
	    errCode = "INCOMPLETE";
	    goto errorMsg;
	case 's':
	    if (gotPrecision) {
		numChars = Tcl_GetCharLength(segment);
		if (precision < numChars) {



		    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)) {
		/* Special case for handling high surrogates. */
		length += Tcl_UniCharToUtf(-1, buf + length);
	    }

	    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;
	    Tcl_WideInt w;
	    mp_int big;
	    int toAppend, isNegative = 0;


#ifndef TCL_WIDE_INT_IS_LONG
	    if (ch == 'p') {
		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 (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;


#endif
	    } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
		if (TclGetWideBitsFromObj(interp, segment, &w) != TCL_OK) {
		    goto error;
		} else {
		    l = (long) w;
		}
		if (useShort) {
		    s = (short) l;
		    isNegative = (s < (short) 0);
		    if (s == (short) 0) gotHash = 0;


		} else {
		    isNegative = (l < (long) 0);
		    if (l == (long) 0) gotHash = 0;


		}
	    } else if (useShort) {
		s = (short) l;
		isNegative = (s < (short) 0);
		if (s == (short) 0) gotHash = 0;


	    } else {
		isNegative = (l < (long) 0);
		if (l == (long) 0) gotHash = 0;


	    }

	    TclNewObj(segment);
	    allocSegment = 1;
	    segmentLimit = INT_MAX;
	    Tcl_IncrRefCount(segment);

	    if ((isNegative || gotPlus || gotSpace) && (useBig || ch=='d')) {
		Tcl_AppendToObj(segment,
			(isNegative ? "-" : gotPlus ? "+" : " "), 1);
		segmentLimit -= 1;
	    }







>
>
>
|
>













|
|
<
<

>



















|
>













|
>
>
















|
>
>










|
>
>


|
>
>




|
>
>


|
>
>




|







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
	    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);
		    }
		    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;
	    }
	    if ((unsigned)code > 0x10FFFF) {
	    	code = 0xFFFD;


	    }
	    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;
	    Tcl_WideInt w;
	    mp_int big;
	    int isNegative = 0;
	    Tcl_Size toAppend;

#ifndef TCL_WIDE_INT_IS_LONG
	    if (ch == 'p') {
		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 (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;
		}
#endif
	    } else if (TclGetLongFromObj(NULL, segment, &l) != TCL_OK) {
		if (TclGetWideBitsFromObj(interp, segment, &w) != TCL_OK) {
		    goto error;
		} else {
		    l = (long) w;
		}
		if (useShort) {
		    s = (short) l;
		    isNegative = (s < (short) 0);
		    if (s == (short) 0) {
			gotHash = 0;
		    }
		} else {
		    isNegative = (l < (long) 0);
		    if (l == (long) 0) {
			gotHash = 0;
		    }
		}
	    } else if (useShort) {
		s = (short) l;
		isNegative = (s < (short) 0);
		if (s == (short) 0) {
		    gotHash = 0;
		}
	    } else {
		isNegative = (l < (long) 0);
		if (l == (long) 0) {
		    gotHash = 0;
		}
	    }

	    TclNewObj(segment);
	    allocSegment = 1;
	    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
		    Tcl_AppendToObj(segment, "0x", 2);
		    segmentLimit -= 2;
		    break;
		case 'b':
		    Tcl_AppendToObj(segment, "0b", 2);
		    segmentLimit -= 2;
		    break;




		}
	    }

	    switch (ch) {
	    case 'd': {
		size_t length;
		Tcl_Obj *pure;
		const char *bytes;

		if (useShort) {
		    TclNewIntObj(pure, s);
#ifndef TCL_WIDE_INT_IS_LONG
		} else if (useWide) {







>
>
>
>





|







2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
		    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': {
		Tcl_Size length;
		Tcl_Obj *pure;
		const char *bytes;

		if (useShort) {
		    TclNewIntObj(pure, s);
#ifndef TCL_WIDE_INT_IS_LONG
		} else if (useWide) {
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
		/*
		 * 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) {
			segmentLimit -= precision - length;
		    }
		    while (length < (size_t)precision) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		    gotZero = 0;
		}
		if (gotZero) {
		    length += Tcl_GetCharLength(segment);
		    if (length < (size_t)width) {
			segmentLimit -= width - length;
		    }
		    while (length < (size_t)width) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		}
		if (toAppend > segmentLimit) {
		    msg = overflow;
		    errCode = "OVERFLOW";







|


|







|


|







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
		/*
		 * 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 < precision) {
			segmentLimit -= precision - length;
		    }
		    while (length < precision) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		    gotZero = 0;
		}
		if (gotZero) {
		    length += Tcl_GetCharLength(segment);
		    if (length < width) {
			segmentLimit -= width - length;
		    }
		    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
	    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_Obj *pure;
		char *bytes;

		if (ch == 'u') {
		    base = 10;
		} else if (ch == 'o') {
		    base = 8;







|







2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
	    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;
		Tcl_Size length;
		Tcl_Obj *pure;
		char *bytes;

		if (ch == 'u') {
		    base = 10;
		} else if (ch == 'o') {
		    base = 8;
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
		    }
		    bits /= base;
		}
		if (useBig) {
		    mp_clear(&big);
		}
		if (gotPrecision) {
		    if (length < (size_t)precision) {
			segmentLimit -= precision - length;
		    }
		    while (length < (size_t)precision) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		    gotZero = 0;
		}
		if (gotZero) {
		    length += Tcl_GetCharLength(segment);
		    if (length < (size_t)width) {
			segmentLimit -= width - length;
		    }
		    while (length < (size_t)width) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		}
		if (toAppend > segmentLimit) {
		    msg = overflow;
		    errCode = "OVERFLOW";







|


|







|


|







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
		    }
		    bits /= base;
		}
		if (useBig) {
		    mp_clear(&big);
		}
		if (gotPrecision) {
		    if (length < precision) {
			segmentLimit -= precision - length;
		    }
		    while (length < precision) {
			Tcl_AppendToObj(segment, "0", 1);
			length++;
		    }
		    gotZero = 0;
		}
		if (gotZero) {
		    length += Tcl_GetCharLength(segment);
		    if (length < width) {
			segmentLimit -= width - length;
		    }
		    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
	    if (gotSpace) {
		*p++ = ' ';
	    }
	    if (gotPlus) {
		*p++ = '+';
	    }
	    if (width) {
		p += sprintf(p, "%d", width);
		if (width > length) {
		    length = width;
		}
	    }
	    if (gotPrecision) {
		*p++ = '.';
		p += sprintf(p, "%d", precision);
		if (precision > INT_MAX - length) {
		    msg = overflow;
		    errCode = "OVERFLOW";
		    goto errorMsg;
		}
		length += precision;
	    }








|






|
|







2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
	    if (gotSpace) {
		*p++ = ' ';
	    }
	    if (gotPlus) {
		*p++ = '+';
	    }
	    if (width) {
		p += snprintf(p, TCL_INTEGER_SPACE, "%" TCL_LL_MODIFIER "d", width);
		if (width > length) {
		    length = width;
		}
	    }
	    if (gotPrecision) {
		*p++ = '.';
		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;
	    }

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
	    allocSegment = 1;
	    if (!Tcl_AttemptSetObjLength(segment, length)) {
		msg = overflow;
		errCode = "OVERFLOW";
		goto errorMsg;
	    }
	    bytes = TclGetString(segment);
	    if (!Tcl_AttemptSetObjLength(segment, sprintf(bytes, spec, d))) {
		msg = overflow;
		errCode = "OVERFLOW";
		goto errorMsg;
	    }
	    if (ch == 'A') {
		char *q = TclGetString(segment) + 1;
		*q = 'x';
		q = strchr(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);
	    }
	    goto error;
	}

	if (width>0 && numChars<0) {
	    numChars = Tcl_GetCharLength(segment);
	}







|








|
>
>







|







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
	    allocSegment = 1;
	    if (!Tcl_AttemptSetObjLength(segment, length)) {
		msg = overflow;
		errCode = "OVERFLOW";
		goto errorMsg;
	    }
	    bytes = TclGetString(segment);
	    if (!Tcl_AttemptSetObjLength(segment, snprintf(bytes, segment->length, spec, d))) {
		msg = overflow;
		errCode = "OVERFLOW";
		goto errorMsg;
	    }
	    if (ch == 'A') {
		char *q = TclGetString(segment) + 1;
		*q = 'x';
		q = strchr(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", (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
    }

    return TCL_OK;

  errorMsg:
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
	Tcl_SetErrorCode(interp, "TCL", "FORMAT", errCode, NULL);
    }
  error:
    Tcl_SetObjLength(appendObj, originalLength);
    return TCL_ERROR;
}

/*







|







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, (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
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_Format(
    Tcl_Interp *interp,
    const char *format,
    int objc,
    Tcl_Obj *const objv[])
{
    int result;
    Tcl_Obj *objPtr;

    TclNewObj(objPtr);
    result = Tcl_AppendFormatToObj(interp, objPtr, format, objc, objv);







|







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,
    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
 *
 * Results:
 *
 * Side effects:
 *
 *---------------------------------------------------------------------------
 */



























static void
AppendPrintfToObjVA(
    Tcl_Obj *objPtr,
    const char *format,
    va_list argList)
{
    int code, objc;

    Tcl_Obj **objv, *list;
    const char *p;

    TclNewObj(list);
    p = format;
    Tcl_IncrRefCount(list);
    while (*p != '\0') {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|
>







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;
    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

		/*
		 * 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);
		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 '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(
			    va_arg(argList, int)));
		    break;
		case 1:
		    Tcl_ListObjAppendElement(NULL, list, Tcl_NewWideIntObj(
			    va_arg(argList, long)));
		    break;
		case 2:
		    Tcl_ListObjAppendElement(NULL, list, Tcl_NewWideIntObj(
			    va_arg(argList, Tcl_WideInt)));
		    break;
		case 3:
		    Tcl_ListObjAppendElement(NULL, list, Tcl_NewBignumObj(
			    va_arg(argList, mp_int *)));
		    break;
		}







|















>
>
>
>
>





<






|



|



|







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 = 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 'x':
	    case 'X':
		seekingConversion = 0;
		switch (size) {
		case -1:
		case 0:
		    Tcl_ListObjAppendElement(NULL, list, Tcl_NewIntObj(
			    va_arg(argList, int)));
		    break;
		case 1:
		    Tcl_ListObjAppendElement(NULL, list, NewLongObj(*p,
			    va_arg(argList, long)));
		    break;
		case 2:
		    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
 *
 *---------------------------------------------------------------------------
 */

char *
TclGetStringStorage(
    Tcl_Obj *objPtr,
    size_t *sizePtr)
{
    String *stringPtr;

    if (!TclHasIntRep(objPtr, &tclStringType) || objPtr->bytes == NULL) {
	return TclGetStringFromObj(objPtr, sizePtr);
    }

    stringPtr = GET_STRING(objPtr);
    *sizePtr = stringPtr->allocated;
    return objPtr->bytes;
}







|



|







2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
 *
 *---------------------------------------------------------------------------
 */

char *
TclGetStringStorage(
    Tcl_Obj *objPtr,
    Tcl_Size *sizePtr)
{
    String *stringPtr;

    if (!TclHasInternalRep(objPtr, &tclStringType) || objPtr->bytes == NULL) {
	return TclGetStringFromObj(objPtr, sizePtr);
    }

    stringPtr = GET_STRING(objPtr);
    *sizePtr = stringPtr->allocated;
    return objPtr->bytes;
}
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
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringRepeat(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    size_t count,
    int flags)
{
    Tcl_Obj *objResultPtr;
    int inPlace = flags & TCL_STRING_IN_PLACE;

    size_t length = 0, unichar = 0, done = 1;

    int binary = TclIsPureByteArray(objPtr);

    /* 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.
     */

    if (!binary) {
	if (TclHasIntRep(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);

    } else if (unichar) {
	/* Result will be pure Tcl_UniChar array. Pre-size it. */
	(void)TclGetUnicodeFromObj(objPtr, &length);

    } else {
	/* Result will be concat of string reps. Pre-size it. */
	(void)TclGetStringFromObj(objPtr, &length);

    }

    if (length == 0) {
	/* Any repeats of empty is empty. */
	return objPtr;
    }


    if (count > INT_MAX/length) {
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(


		    "max size for a Tcl value (%d bytes) exceeded", INT_MAX));

	    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	}
	return NULL;
    }

    if (binary) {
	/* Efficiently produce a pure byte array result */
	objResultPtr = (!inPlace || Tcl_IsShared(objPtr)) ?
		Tcl_DuplicateObj(objPtr) : objPtr;


	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),
		(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;
	}


        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(count*length)));
		Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	    }
	    return NULL;
	}
	Tcl_SetObjLength(objResultPtr, length);
	while (count - done > done) {
	    Tcl_AppendObjToObj(objResultPtr, objResultPtr);
	    done *= 2;
	}
	TclAppendUnicodeToObj(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);
	    objResultPtr = objPtr;
	}

        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",
			count*length));
		Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
	    }
	    return NULL;
	}
	Tcl_SetObjLength(objResultPtr, length);
	while (count - done > done) {
	    Tcl_AppendObjToObj(objResultPtr, objResultPtr);
	    done *= 2;







|




>
|
>

|
<









|









|
>


|
>



>







>
|

|
>
>
|
>
|









>







|













>
|



|

|








|









|


>
|


|

|







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
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringRepeat(
    Tcl_Interp *interp,
    Tcl_Obj *objPtr,
    Tcl_Size count,
    int flags)
{
    Tcl_Obj *objResultPtr;
    int inPlace = flags & TCL_STRING_IN_PLACE;
    Tcl_Size length = 0;
    int unichar = 0;
    Tcl_Size done = 1;
    int binary = TclIsPureByteArray(objPtr);
    Tcl_Size maxCount;


    /*
     * Analyze to determine what representation result should be.
     * GOALS:	Avoid shimmering & string rep generation.
     * 		Produce pure bytearray when possible.
     * 		Error on overflow.
     */

    if (!binary) {
	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)Tcl_GetBytesFromObj(NULL, objPtr, &length);
	maxCount = TCL_SIZE_MAX;
    } else if (unichar) {
	/* Result will be pure Tcl_UniChar array. Pre-size it. */
	(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 > (maxCount-1)) {
	if (interp) {
	    Tcl_SetObjResult(
		interp,
		Tcl_ObjPrintf("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_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 (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"string size overflow: unable to alloc %"
			TCL_SIZE_MODIFIER "d bytes",
			STRING_SIZE(count*length)));
		Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	    }
	    return NULL;
	}
	Tcl_SetObjLength(objResultPtr, length);
	while (count - done > done) {
	    Tcl_AppendObjToObj(objResultPtr, objResultPtr);
	    done *= 2;
	}
	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 {
	    TclFreeInternalRep(objPtr);
	    objResultPtr = objPtr;
	}
	/* TODO - overflow check */
	if (0 == Tcl_AttemptSetObjLength(objResultPtr, count*length)) {
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"string size overflow: unable to alloc %" TCL_SIZE_MODIFIER "d bytes",
			count*length));
		Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
	    }
	    return NULL;
	}
	Tcl_SetObjLength(objResultPtr, length);
	while (count - done > done) {
	    Tcl_AppendObjToObj(objResultPtr, objResultPtr);
	    done *= 2;
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
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringCat(
    Tcl_Interp *interp,
    int 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;

    /* assert ( objc >= 0 ) */

    if (objc <= 1) {
	/* Only one or no objects; return first or empty */


	return objc ? objv[0] : Tcl_NewObj();
    }



    /* 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.
     */








|




|
|
|
|
|
|

<
|
|
|
>
>
|
|
>
>
|
<








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
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringCat(
    Tcl_Interp *interp,
    Tcl_Size objc,
    Tcl_Obj * const objv[],
    int flags)
{
    Tcl_Obj *objResultPtr, * const *ov;
    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);


    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];
    }


    /*
     * Analyze to determine what representation result should be.
     * GOALS:	Avoid shimmering & string rep generation.
     * 		Produce pure bytearray when possible.
     * 		Error on overflow.
     */

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
	    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)) {
		    /* Prevent shimmer of non-string types. */
		    allowUniChar = 0;
		}
	    }
	} else {
	    /* assert (objPtr->typePtr != NULL) -- stork! */
	    binary = 0;
	    if (TclHasIntRep(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;
	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? */

		if (numBytes) {
		    last = objc - oc;
		    if (length == 0) {
			first = last;



		    }
		    length += numBytes;
		}
	    }
	} while (--oc);
    } else if (allowUniChar && requestUniChar) {
	/*
	 * 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;

		(void)TclGetUnicodeFromObj(objPtr, &numChars); /* PANIC? */
		if (numChars) {
		    last = objc - oc;
		    if (length == 0) {
			first = last;



		    }
		    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) {

		    /* No string rep; Take the chance we can avoid making it */
		    pendingPtr = objPtr;
		} else {
		    (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,
	     * or (oc == 0) and all values are known empty,
 	     * so first = last = objc - 1 signals the right quick return.
 	     */

	    first = last = objc - oc - 1;

	    if (oc && (length == 0)) {
		size_t 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.
		 */








>
>
|





<

|














|












|





>
>
>





|










|

|




>
>
>

















<
<
<


|
>



|













|
<
<







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
	    if (objPtr->length) {
		/*
		 * Non-empty string rep. Not a pure bytearray, so we won't
		 * create a pure bytearray.
		 */

	 	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 {

	    binary = 0;
	    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
	 */

	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)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) || 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)) {
		Tcl_Size numChars;

		(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 {



		Tcl_Obj *objPtr = *ov++;

		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? */
		}
	    } 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,
	     * or (oc == 0) and all values are known empty,
 	     * so first = last = objc - 1 signals the right quick return.
 	     */

	    first = last = objc - oc - 1;

	    if (oc && (length == 0)) {
		Tcl_Size numBytes;



		/*
		 * 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
		if (oc || numBytes) {
		    (void)TclGetStringFromObj(pendingPtr, &length);
		}
		if (length == 0) {
		    if (numBytes) {
			first = last;
		    }
		} else if (numBytes + length > (size_t)INT_MAX) {
		    goto overflow;
		}
		length += numBytes;
	    }
	} while (oc && (length == 0));

	while (oc) {
	    size_t 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) {
		    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);


    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;

	    objResultPtr = *objv++; objc--;
	    (void)TclGetByteArrayFromObj(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);
		memcpy(dst, src, more);
		dst += more;
	    }
	}
    } else if (allowUniChar && requestUniChar) {
	/* Efficiently produce a pure Tcl_UniChar array result */
	Tcl_UniChar *dst;

	if (inPlace && !Tcl_IsShared(*objv)) {
	    size_t start;

	    objResultPtr = *objv++; objc--;

	    /* Ugly interface! Force resize of the unicode array. */
	    (void)TclGetUnicodeFromObj(objResultPtr, &start);
	    Tcl_InvalidateStringRep(objResultPtr);
	    if (0 == Tcl_AttemptSetObjLength(objResultPtr, length)) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    	"concatenation failed: unable to alloc %"
			TCL_Z_MODIFIER "u bytes",
			STRING_SIZE(length)));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", 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 %"
			TCL_Z_MODIFIER "u bytes",
			STRING_SIZE(length)));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", 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);
		memcpy(dst, src, more * sizeof(Tcl_UniChar));
		dst += more;
	    }
	}
    } else {
	/* Efficiently concatenate string reps */
	char *dst;

	if (inPlace && !Tcl_IsShared(*objv)) {
	    size_t 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",
			length));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		}
		return NULL;
	    }
	    dst = TclGetString(objResultPtr) + start;

	    /* assert ( length > start ) */
	    TclFreeIntRep(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",
			length));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		}
		return NULL;
	    }
	    dst = TclGetString(objResultPtr);
	}
	while (objc--) {
	    Tcl_Obj *objPtr = *objv++;

	    if ((objPtr->bytes == NULL) || (objPtr->length)) {
		size_t 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);
    }
    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.
 *
 *---------------------------------------------------------------------------
 */

















































































































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 */

{
    char *s1, *s2;
    int empty, match;
    size_t 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.

	 */
	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);
	    memCmpFn = memcmp;
	} else if (TclHasIntRep(value1Ptr, &tclStringType)
		&& TclHasIntRep(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.
	     */

	    if (nocase) {
		s1 = (char *) TclGetUnicodeFromObj(value1Ptr, &s1len);
		s2 = (char *) TclGetUnicodeFromObj(value2Ptr, &s2len);
		memCmpFn = (memCmpFn_t)TclUniCharNcasecmp;
	    } else {
		s1len = Tcl_GetCharLength(value1Ptr);
		s2len = Tcl_GetCharLength(value2Ptr);
		if ((s1len == value1Ptr->length)
			&& (value1Ptr->bytes != NULL)
			&& (s2len == value2Ptr->length)
			&& (value2Ptr->bytes != NULL)) {



		    s1 = value1Ptr->bytes;
		    s2 = value2Ptr->bytes;
		    memCmpFn = memcmp;
		} else {
		    s1 = (char *) Tcl_GetUnicode(value1Ptr);
		    s2 = (char *) Tcl_GetUnicode(value2Ptr);
		    if (
#ifdef WORDS_BIGENDIAN
			    1
#else
			    checkEq
#endif
			    ) {
			memCmpFn = memcmp;
			s1len *= sizeof(Tcl_UniChar);
			s2len *= sizeof(Tcl_UniChar);



		    } else {
			memCmpFn = (memCmpFn_t) TclUniCharNcmp;
		    }
		}
	    }
	} else {
	    empty = TclCheckEmptyString(value1Ptr);
	    if (empty > 0) {
		switch (TclCheckEmptyString(value2Ptr)) {
		case -1:
		    s1 = 0;
		    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;
		    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) {
		/*
		 * 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;
		} else {
		    s1len = Tcl_NumUtfChars(s1, s1len);
		    s2len = Tcl_NumUtfChars(s2, s2len);
		    memCmpFn = (memCmpFn_t)
			    (nocase ? Tcl_UtfNcasecmp : Tcl_UtfNcmp);
		}
	    }
	}





	length = (s1len < s2len) ? s1len : s2len;
	if (reqlength == TCL_INDEX_NONE) {
	    /*
	     * The requested length is negative, so we ignore it by setting it
	     * to length + 1 so we correct the match var.
	     */

	    reqlength = length + 1;
	} else if (reqlength > 0 && reqlength < length) {
	    length = reqlength;
	}

	if (checkEq && (s1len != s2len)) {
	    match = 1;		/* This will be reversed below. */
	} else {
	    /*
	     * The comparison function should compare up to the minimum byte
	     * length only.
	     */








|







|


<
<




|















>










|
|


|















|
|




|



|
|




|







|
















|









|
|








|
|







|

|





<
|






|

|









|














|
|




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|
>

|

|





>












|
|

|
|

|
|
|
|



|
|
|







>
>
>







|








>
>
>

|








|














|















|
















|
|



|
<




>
>
>
>

|

|
|







|







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
		if (oc || numBytes) {
		    (void)TclGetStringFromObj(pendingPtr, &length);
		}
		if (length == 0) {
		    if (numBytes) {
			first = last;
		    }
		} else if (numBytes > (TCL_SIZE_MAX - length)) {
		    goto overflow;
		}
		length += numBytes;
	    }
	} while (oc && (length == 0));

	while (oc) {
	    Tcl_Size numBytes;
	    Tcl_Obj *objPtr = *ov++;



	    TclGetString(objPtr); /* PANIC? */
	    numBytes = objPtr->length;
	    if (numBytes) {
		last = objc - oc;
		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_Size start = 0;

	    objResultPtr = *objv++; objc--;
	    (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)) {
		Tcl_Size more = 0;
		unsigned char *src = Tcl_GetBytesFromObj(NULL, objPtr, &more);
		memcpy(dst, src, more);
		dst += more;
	    }
	}
    } else if ((allowUniChar && requestUniChar) || forceUniChar) {
	/* Efficiently produce a pure Tcl_UniChar array result */
	Tcl_UniChar *dst;

	if (inPlace) {
	    Tcl_Size start;

	    objResultPtr = *objv++; objc--;

	    /* Ugly interface! Force resize of the unicode array. */
	    (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 %"
			TCL_Z_MODIFIER "u bytes",
			STRING_SIZE(length)));
		    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 %"
			TCL_Z_MODIFIER "u bytes",
			STRING_SIZE(length)));
		    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)) {
		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_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_SIZE_MODIFIER "d bytes",
			length));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
		}
		return NULL;
	    }
	    dst = TclGetString(objResultPtr) + start;


	    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_SIZE_MODIFIER "d bytes",
			length));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", (char *)NULL);
		}
		return NULL;
	    }
	    dst = TclGetString(objResultPtr);
	}
	while (objc--) {
	    Tcl_Obj *objPtr = *objv++;

	    if ((objPtr->bytes == NULL) || (objPtr->length)) {
		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 (%" 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 */
    Tcl_Size reqlength)		/* requested length in characters;
						 * TCL_INDEX_NONE to compare whole strings */
{
    const char *s1, *s2;
    int empty, match;
    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 *) Tcl_GetBytesFromObj(NULL, value1Ptr, &s1len);
	    s2 = (char *) Tcl_GetBytesFromObj(NULL, value2Ptr, &s2len);
	    memCmpFn = memcmp;
	} 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.
	     */

	    if (nocase) {
		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 (
#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 = UniCharNmemcmp;
		    }
		}
	    }
	} else {
	    empty = TclCheckEmptyString(value1Ptr);
	    if (empty > 0) {
		switch (TclCheckEmptyString(value2Ptr)) {
		case -1:
		    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 = "";
		    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 && 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 < 0) && !nocase) {
		    memCmpFn = TclpUtfNcmp2;
		} else {
		    s1len = Tcl_NumUtfChars(s1, s1len);
		    s2len = Tcl_NumUtfChars(s2, s2len);
		    memCmpFn = nocase ? UtfNcasememcmp : UtfNmemcmp;

		}
	    }
	}

	/* 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 < 0) {
	    /*
	     * 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 && 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
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringFirst(
    Tcl_Obj *needle,
    Tcl_Obj *haystack,
    size_t start)
{
    size_t lh = 0, ln = Tcl_GetCharLength(needle);
    size_t value = TCL_INDEX_NONE;
    Tcl_UniChar *checkStr, *endStr, *uh, *un;
    Tcl_Obj *obj;

    if (start == TCL_INDEX_NONE) {
	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);

	/* Find bytes in bytes */
	bh = TclGetByteArrayFromObj(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;







|

|
|



|











|


|







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
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringFirst(
    Tcl_Obj *needle,
    Tcl_Obj *haystack,
    Tcl_Size start)
{
    Tcl_Size lh = 0, ln = Tcl_GetCharLength(needle);
    Tcl_Size value = -1;
    Tcl_UniChar *checkStr, *endStr, *uh, *un;
    Tcl_Obj *obj;

    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 = Tcl_GetBytesFromObj(NULL, needle, &ln);

	/* Find bytes in bytes */
	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
     * 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);
    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++) {







|
|







3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
     * 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 = 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
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringLast(
    Tcl_Obj *needle,
    Tcl_Obj *haystack,
    size_t last)
{
    size_t lh = 0, ln = Tcl_GetCharLength(needle);
    size_t value = TCL_INDEX_NONE;
    Tcl_UniChar *checkStr, *uh, *un;
    Tcl_Obj *obj;

    if (ln == 0) {
	/*
	 * 	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.
	 */
	goto lastEnd;
    }

    if (TclIsPureByteArray(needle) && TclIsPureByteArray(haystack)) {
	unsigned char *check, *bh = TclGetByteArrayFromObj(haystack, &lh);
	unsigned char *bn = TclGetByteArrayFromObj(needle, &ln);

	if (last + 1 >= lh + 1) {
	    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);

    if (last + 1 >= lh + 1) {
	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;







|

|
|














|
|

|



















|
|

|







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
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringLast(
    Tcl_Obj *needle,
    Tcl_Obj *haystack,
    Tcl_Size last)
{
    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!
	 *
	 * 	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 = Tcl_GetBytesFromObj(NULL, haystack, &lh);
	unsigned char *bn = Tcl_GetBytesFromObj(NULL, needle, &ln);

	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 = Tcl_GetUnicodeFromObj(haystack, &lh);
    un = Tcl_GetUnicodeFromObj(needle, &ln);

    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
 *---------------------------------------------------------------------------
 */

static void
ReverseBytes(
    unsigned char *to,		/* Copy bytes into here... */
    unsigned char *from,	/* ...from here... */
    size_t count)		/* Until this many are copied, */
				/* reversing as you go. */
{
    unsigned char *src = from + count;

    if (to == from) {
	/* Reversing in place */
	while (--src > to) {







|







4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
 *---------------------------------------------------------------------------
 */

static void
ReverseBytes(
    unsigned char *to,		/* Copy bytes into here... */
    unsigned char *from,	/* ...from here... */
    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
    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);

	if (!inPlace || Tcl_IsShared(objPtr)) {
	    objPtr = Tcl_NewByteArrayObj(NULL, numBytes);
	}
	ReverseBytes(Tcl_GetByteArrayFromObj(objPtr, NULL), from, numBytes);
	return objPtr;
    }

    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);

    if (stringPtr->hasUnicode) {
	Tcl_UniChar *from = Tcl_GetUnicode(objPtr);

	Tcl_UniChar *src = from + stringPtr->numChars;

	if (!inPlace || Tcl_IsShared(objPtr)) {
	    Tcl_UniChar *to;


	    /*
	     * 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);

	    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;
	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)) {
	    /*
	     * 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;


	    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);

		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;
}







|
|




|








>

<
<
|

>

|
|





>

















|
|








|









<
|
>








|






<



<







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
    int flags)
{
    String *stringPtr;
    Tcl_UniChar ch = 0;
    int inPlace = flags & TCL_STRING_IN_PLACE;

    if (TclIsPureByteArray(objPtr)) {
	Tcl_Size numBytes = 0;
	unsigned char *from = Tcl_GetBytesFromObj(NULL, objPtr, &numBytes);

	if (!inPlace || Tcl_IsShared(objPtr)) {
	    objPtr = Tcl_NewByteArrayObj(NULL, 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;


	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.
	     */

	    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) {
	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 < 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.
	     */


	    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.
		 */

		int bytesInChar = TclUtfToUniChar(from, &chw);

		ReverseBytes((unsigned char *)to, (unsigned char *)from,
			bytesInChar);
		to += bytesInChar;
		from += bytesInChar;
		bytesLeft -= bytesInChar;

	    }

	    from = to = objPtr->bytes;

	}
	/* 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
 *---------------------------------------------------------------------------
 */

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_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 (inPlace) {
	    return objPtr;
	} else {
	    return Tcl_DuplicateObj(objPtr);
	}



    }

    /*
     * 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);

	if (insertPtr == NULL) {
	    /* Replace something with nothing. */

	    assert ( first <= numBytes ) ;
	    assert ( count <= numBytes ) ;
	    assert ( first + count <= numBytes ) ;







|
|







|





>
>
>










|
|







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
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringReplace(
    Tcl_Interp *interp,		/* For error reporting, may be NULL */
    Tcl_Obj *objPtr,		/* String to act upon */
    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 (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)) {
	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

	/* Replace everything */
	if ((first == 0) && (count == numBytes)) {
	    return insertPtr;
	}

	if (TclIsPureByteArray(insertPtr)) {
	    size_t newBytes = 0;
	    unsigned char *iBytes
		    = TclGetByteArrayFromObj(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 (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "max size for a Tcl value (%d bytes) exceeded",
			    INT_MAX));
		    Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
		}
		return NULL;
	    }
	    result = Tcl_NewByteArrayObj(NULL, numBytes - count + newBytes);
								/* PANIC? */
	    Tcl_SetByteArrayLength(result, 0);
	    TclAppendBytesToByteArray(result, bytes, first);







|

|












|


|
|
|







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

	/* Replace everything */
	if ((first == 0) && (count == numBytes)) {
	    return insertPtr;
	}

	if (TclIsPureByteArray(insertPtr)) {
	    Tcl_Size newBytes = 0;
	    unsigned char *iBytes
		    = 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 (newBytes > (TCL_SIZE_MAX - (numBytes - count))) {
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "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
     * 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);

	/* 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,
		    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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Reallocates the String internal rep.
 *







|
|







|
|













|







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
     * 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... */
    {
	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) < 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 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
	    stringPtr->numChars);
}

static void
ExtendUnicodeRepWithString(
    Tcl_Obj *objPtr,
    const char *bytes,
    size_t numBytes,
    size_t numAppendChars)
{
    String *stringPtr = GET_STRING(objPtr);
    size_t needed, numOrigChars = 0;
    Tcl_UniChar *dst, unichar = 0;

    if (stringPtr->hasUnicode) {
	numOrigChars = stringPtr->numChars;
    }
    if (numAppendChars == TCL_INDEX_NONE) {
	TclNumUtfChars(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++) {

	bytes += TclUtfToUniChar(bytes, &unichar);
	*dst = unichar;




    }
    *dst = 0;
}

/*
 *----------------------------------------------------------------------
 *







|
|


|






|














|
>

|
>
>
>
>







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
	    stringPtr->numChars);
}

static void
ExtendUnicodeRepWithString(
    Tcl_Obj *objPtr,
    const char *bytes,
    Tcl_Size numBytes,
    Tcl_Size numAppendChars)
{
    String *stringPtr = GET_STRING(objPtr);
    Tcl_Size needed, numOrigChars = 0;
    Tcl_UniChar *dst, unichar = 0;

    if (stringPtr->hasUnicode) {
	numOrigChars = stringPtr->numChars;
    }
    if (numAppendChars == TCL_INDEX_NONE) {
	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;
    }
    dst = stringPtr->unicode + numOrigChars;
    if (numAppendChars-- > 0) {
	bytes += TclUtfToUniChar(bytes, &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

    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) {







<







4394
4395
4396
4397
4398
4399
4400

4401
4402
4403
4404
4405
4406
4407

    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
 *
 *	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".
 *
 *----------------------------------------------------------------------
 */

static int
SetStringFromAny(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *objPtr)		/* The object to convert. */
{
    if (!TclHasIntRep(objPtr, &tclStringType)) {
	String *stringPtr = stringAlloc(0);

	/*
	 * Convert whatever we have into an untyped value. Just A String.
	 */

	(void) TclGetString(objPtr);
	TclFreeIntRep(objPtr);

	/*
	 * Create a basic String intrep 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;







|
|









|







|


|







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
 *
 *	Create an internal representation of type "String" for an object.
 *
 * Results:
 *	This operation always succeeds and returns TCL_OK.
 *
 * Side effects:
 *	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 (!TclHasInternalRep(objPtr, &tclStringType)) {
	String *stringPtr = stringAlloc(0);

	/*
	 * Convert whatever we have into an untyped value. Just A String.
	 */

	(void) TclGetString(objPtr);
	TclFreeInternalRep(objPtr);

	/*
	 * 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
 *	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
 *	to UTF format.
 *
 *----------------------------------------------------------------------
 */

static void
UpdateStringOfString(







|







4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
 *	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 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
     * 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);
    } else {
	(void) ExtendStringRepWithUnicode(objPtr, stringPtr->unicode,
		stringPtr->numChars);
    }
}

static size_t
ExtendStringRepWithUnicode(
    Tcl_Obj *objPtr,
    const Tcl_UniChar *unicode,
    size_t numChars)
{
    /*
     * Pre-condition: this is the "string" Tcl_ObjType.
     */

    size_t i, origLength, size = 0;
    char *dst;
    String *stringPtr = GET_STRING(objPtr);

    if (numChars == TCL_INDEX_NONE) {
	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
	    && stringPtr->allocated >= size + numChars * TCL_UTF_MAX) {
	goto copyBytes;
    }

    for (i = 0; i < numChars; i++) {

	size += TclUtfCount(unicode[i]);
    }




    /*
     * Grow space if needed.
     */

    if (size > stringPtr->allocated) {
	GrowStringBuffer(objPtr, size, 1);







|






|



|


|


|



|
















|




|
>


>
>
>







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
     * memory pointed to by that NULL pointer is clearly bogus, and
     * needs a reset.
     */

    stringPtr->allocated = 0;

    if (stringPtr->numChars == 0) {
	TclInitEmptyStringRep(objPtr);
    } else {
	(void) ExtendStringRepWithUnicode(objPtr, stringPtr->unicode,
		stringPtr->numChars);
    }
}

static Tcl_Size
ExtendStringRepWithUnicode(
    Tcl_Obj *objPtr,
    const Tcl_UniChar *unicode,
    Tcl_Size numChars)
{
    /*
     * Precondition: this is the "string" Tcl_ObjType.
     */

    Tcl_Size i, origLength, size = 0;
    char *dst;
    String *stringPtr = GET_STRING(objPtr);

    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 <= (TCL_SIZE_MAX - size)/TCL_UTF_MAX
	    && stringPtr->allocated >= size + numChars * TCL_UTF_MAX) {
	goto copyBytes;
    }

    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
/*
 * tclStringRep.h --
 *
 *	This file contains the definition of the Unicode string internal
 *	representation and macros to access it.
 *
 *	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
 *	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
 *	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
 *	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
 * length and indexing operations, this structure also stores the number of
 * characters (same of UTF and Unicode!) 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. */
    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. */
} String;





#define STRING_SIZE(numChars) \
    (offsetof(String, unicode) + ((numChars + 1) * 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) \



|
|

|
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<















|
|

|
<
<
<
<
<



|
|
|
|
|
|
|
|
>
|
|

|
|
|
|


>
>
>
>

|







1
2
3
4
5
6
7











8

9





10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28





29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/*
 * tclStringRep.h --
 *
 *  This file contains the definition of internal representations of a string
 *  and macros to access it.
 *
 *  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.





 *
 * 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 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
 * code points (independent of encoding form) once that value has been computed.





 */

typedef struct {
    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 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) + 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
/*
 * tclStubInit.c --
 *
 *	This file contains the initializers for the Tcl stub vectors.
 *
 * 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.
 */

#include "tclInt.h"
#include "tommath_private.h"





|







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 © 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
#undef Tcl_FindExecutable
#undef Tcl_SetExitProc
#undef Tcl_SetPanicProc
#undef TclpGetPid
#undef TclSockMinimumBuffers
#undef Tcl_SetIntObj
#undef Tcl_SetLongObj

#undef TclpInetNtoa
#undef TclWinGetServByName
#undef TclWinGetSockOpt
#undef TclWinSetSockOpt
#undef TclWinNToHS

#undef TclStaticPackage
#undef Tcl_BackgroundError
#define TclStaticPackage Tcl_StaticPackage
#undef Tcl_UniCharToUtfDString

#undef Tcl_UtfToUniCharDString


#undef Tcl_UtfToUniChar

#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 Tcl_SetUnicodeObj (void(*)(Tcl_Obj *, const Tcl_UniChar *, size_t))(void *)uniCodePanic
#endif



















































































































#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_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_xor mp_xor
#define TclBN_mp_zero mp_zero
#define TclBN_s_mp_add s_mp_add

#define TclBN_s_mp_balance_mul mp_balance_mul
#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_s_mp_sqr s_mp_sqr
#define TclBN_s_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 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
#endif

#ifdef _WIN32
#   define TclUnixWaitForFile 0
#   define TclUnixCopyFile 0
#   define TclUnixOpenTemporaryFile 0
#   define TclpReaddir 0

#   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 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 *hInstance = NULL;
    GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
	    (const wchar_t *)&TclWinNoBackslash, &hInstance);
    return hInstance;
}

size_t
TclpGetPid(Tcl_Pid pid)
{
    return (size_t)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.
 */

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))) {
	    *ptr = (int)longValue;
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "integer value too large to represent as non-long integer", -1));
	    result = TCL_ERROR;
	}
    }
    return result;
}
#define Tcl_ExprLong (int(*)(Tcl_Interp*,const char*,long*))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))) {
	    *ptr = (int)longValue;
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "integer value too large to represent as non-long integer", -1));
	    result = TCL_ERROR;
	}
    }
    return result;
}
#define Tcl_ExprLongObj (int(*)(Tcl_Interp*,Tcl_Obj*,long*))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__ */







/*
 * 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












/* !BEGIN!: Do not edit below this line. */

static const TclIntStubs tclIntStubs = {
    TCL_STUB_MAGIC,
    0,
    0, /* 0 */
    0, /* 1 */







>
|
|
|
|
|
>
|
<
|
|
>
|
>
>
|
|
<
<
<
<
|
|
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















<


















|
>
|













>



>
|


|
|
|

|




<
<

>
|
>
>
|
|
|
>
|







>








|
















|







|


|








>




|
|



|





|




|
|



|





|
<
<
<
<
<
<
<
<
<


|
>
>
>
>
>
>



















>
>
>
>
>
>
>
>
>
>
>







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73




74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261


262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
#undef Tcl_FindExecutable
#undef Tcl_SetExitProc
#undef Tcl_SetPanicProc
#undef TclpGetPid
#undef TclSockMinimumBuffers
#undef Tcl_SetIntObj
#undef Tcl_SetLongObj
#undef Tcl_ListObjGetElements
#undef Tcl_ListObjLength
#undef Tcl_DictObjSize
#undef Tcl_SplitList
#undef Tcl_SplitPath
#undef Tcl_FSSplitPath
#undef Tcl_ParseArgsObjv
#undef TclStaticLibrary

#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)




# define TclGetStringFromObj 0
# define TclGetBytesFromObj 0
# define TclGetUnicodeFromObj 0
# define Tcl_GetAlias 0
#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
#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", (void *)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", (void *)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", (void *)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", (void *)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;
}
#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_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_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_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_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_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



#ifndef MAC_OSX_TCL /* On UNIX, fill with other stub entries */
#   define Tcl_MacOSXOpenVersionedBundleResources 0
#   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 *, 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)
{
    void *hInstance = NULL;
    GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
	    (const wchar_t *)&TclWinNoBackslash, &hInstance);
    return hInstance;
}

Tcl_Size
TclpGetPid(Tcl_Pid 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))) {
	    *ptr = (int)longValue;
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "integer value too large to represent", -1));
	    result = TCL_ERROR;
	}
    }
    return result;
}
#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))) {
	    *ptr = (int)longValue;
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "integer value too large to represent", -1));
	    result = TCL_ERROR;
	}
    }
    return result;
}
#define Tcl_ExprLongObj (int(*)(Tcl_Interp*,Tcl_Obj*,long*))(void *)exprIntObj









#endif /* TCL_WIDE_INT_IS_LONG */

#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
    0, /* 30 */
    TclGetExtension, /* 31 */
    TclGetFrame, /* 32 */
    0, /* 33 */
    0, /* 34 */
    0, /* 35 */
    0, /* 36 */
    TclGetLoadedPackages, /* 37 */
    TclGetNamespaceForQualName, /* 38 */
    TclGetObjInterpProc, /* 39 */
    TclGetOpenMode, /* 40 */
    TclGetOriginalCommand, /* 41 */
    TclpGetUserHome, /* 42 */
    0, /* 43 */
    TclGuessPackageName, /* 44 */
    TclHideUnsafeCommands, /* 45 */
    TclInExit, /* 46 */
    0, /* 47 */
    0, /* 48 */
    0, /* 49 */
    0, /* 50 */
    TclInterpInit, /* 51 */
    0, /* 52 */
    TclInvokeObjectCommand, /* 53 */
    TclInvokeStringCommand, /* 54 */
    TclIsProc, /* 55 */
    0, /* 56 */
    0, /* 57 */
    TclLookupVar, /* 58 */
    0, /* 59 */
    TclNeedSpace, /* 60 */
    TclNewProcBodyObj, /* 61 */
    TclObjCommandComplete, /* 62 */
    TclObjInterpProc, /* 63 */
    TclObjInvoke, /* 64 */
    0, /* 65 */
    0, /* 66 */
    0, /* 67 */
    0, /* 68 */
    TclpAlloc, /* 69 */
    0, /* 70 */







|





|
|








|
|








|







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
    0, /* 30 */
    TclGetExtension, /* 31 */
    TclGetFrame, /* 32 */
    0, /* 33 */
    0, /* 34 */
    0, /* 35 */
    0, /* 36 */
    0, /* 37 */
    TclGetNamespaceForQualName, /* 38 */
    TclGetObjInterpProc, /* 39 */
    TclGetOpenMode, /* 40 */
    TclGetOriginalCommand, /* 41 */
    TclpGetUserHome, /* 42 */
    TclGetObjInterpProc2, /* 43 */
    0, /* 44 */
    TclHideUnsafeCommands, /* 45 */
    TclInExit, /* 46 */
    0, /* 47 */
    0, /* 48 */
    0, /* 49 */
    0, /* 50 */
    TclInterpInit, /* 51 */
    0, /* 52 */
    0, /* 53 */
    0, /* 54 */
    TclIsProc, /* 55 */
    0, /* 56 */
    0, /* 57 */
    TclLookupVar, /* 58 */
    0, /* 59 */
    TclNeedSpace, /* 60 */
    TclNewProcBodyObj, /* 61 */
    TclObjCommandComplete, /* 62 */
    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
    0, /* 94 */
    0, /* 95 */
    TclRenameCommand, /* 96 */
    TclResetShadowedCmdRefs, /* 97 */
    TclServiceIdle, /* 98 */
    0, /* 99 */
    0, /* 100 */
    TclSetPreInitScript, /* 101 */
    TclSetupEnv, /* 102 */
    TclSockGetPort, /* 103 */
    0, /* 104 */
    0, /* 105 */
    0, /* 106 */
    0, /* 107 */
    TclTeardownNamespace, /* 108 */







|







496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
    0, /* 94 */
    0, /* 95 */
    TclRenameCommand, /* 96 */
    TclResetShadowedCmdRefs, /* 97 */
    TclServiceIdle, /* 98 */
    0, /* 99 */
    0, /* 100 */
    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
    0, /* 125 */
    Tcl_GetVariableFullName, /* 126 */
    0, /* 127 */
    Tcl_PopCallFrame, /* 128 */
    Tcl_PushCallFrame, /* 129 */
    Tcl_RemoveInterpResolvers, /* 130 */
    Tcl_SetNamespaceResolvers, /* 131 */
    TclpHasSockets, /* 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, /* 154 */
    0, /* 155 */
    TclRegError, /* 156 */
    TclVarTraceExists, /* 157 */
    0, /* 158 */
    0, /* 159 */
    0, /* 160 */







|



















|
|







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
    0, /* 125 */
    Tcl_GetVariableFullName, /* 126 */
    0, /* 127 */
    Tcl_PopCallFrame, /* 128 */
    Tcl_PushCallFrame, /* 129 */
    Tcl_RemoveInterpResolvers, /* 130 */
    Tcl_SetNamespaceResolvers, /* 131 */
    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 */
    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
    TclpFindExecutable, /* 212 */
    TclGetObjNameOfExecutable, /* 213 */
    TclSetObjNameOfExecutable, /* 214 */
    TclStackAlloc, /* 215 */
    TclStackFree, /* 216 */
    TclPushStackFrame, /* 217 */
    TclPopStackFrame, /* 218 */
    0, /* 219 */
    0, /* 220 */
    0, /* 221 */
    0, /* 222 */
    0, /* 223 */
    TclGetPlatform, /* 224 */
    TclTraceDictPath, /* 225 */
    TclObjBeingDeleted, /* 226 */
    TclSetNsPath, /* 227 */
    0, /* 228 */
    TclPtrMakeUpvar, /* 229 */
    TclObjLookupVar, /* 230 */







|

|
|
|







614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
    TclpFindExecutable, /* 212 */
    TclGetObjNameOfExecutable, /* 213 */
    TclSetObjNameOfExecutable, /* 214 */
    TclStackAlloc, /* 215 */
    TclStackFree, /* 216 */
    TclPushStackFrame, /* 217 */
    TclPopStackFrame, /* 218 */
    TclpCreateTemporaryDirectory, /* 219 */
    0, /* 220 */
    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
    TclSetChildCancelFlags, /* 250 */
    TclRegisterLiteral, /* 251 */
    TclPtrGetVar, /* 252 */
    TclPtrSetVar, /* 253 */
    TclPtrIncrObjVar, /* 254 */
    TclPtrObjMakeUpvar, /* 255 */
    TclPtrUnsetVar, /* 256 */
    TclStaticPackage, /* 257 */
    TclpCreateTemporaryDirectory, /* 258 */
    TclAppendUnicodeToObj, /* 259 */
    TclGetBytesFromObj, /* 260 */

};

static const TclIntPlatStubs tclIntPlatStubs = {
    TCL_STUB_MAGIC,
    0,
#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(MAC_OSX_TCL) /* UNIX */
    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 /* 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 */
    TclWinAddProcess, /* 20 */
    0, /* 21 */
    TclpCreateTempFile, /* 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 */

#endif /* MACOSX */
};

const TclTomMathStubs tclTomMathStubs = {
    TCL_STUB_MAGIC,
    0,
    TclBN_epoch, /* 0 */
    TclBN_revision, /* 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
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
    TclSetChildCancelFlags, /* 250 */
    TclRegisterLiteral, /* 251 */
    TclPtrGetVar, /* 252 */
    TclPtrSetVar, /* 253 */
    TclPtrIncrObjVar, /* 254 */
    TclPtrObjMakeUpvar, /* 255 */
    TclPtrUnsetVar, /* 256 */
    TclStaticLibrary, /* 257 */
    0, /* 258 */
    0, /* 259 */
    0, /* 260 */
    TclUnusedStubEntry, /* 261 */
};

static const TclIntPlatStubs tclIntPlatStubs = {
    TCL_STUB_MAGIC,
    0,

    0, /* 0 */
    TclpCloseFile, /* 1 */
    TclpCreateCommandChannel, /* 2 */
    TclpCreatePipe, /* 3 */
    TclWinGetTclInstance, /* 4 */
    TclUnixWaitForFile, /* 5 */
    TclpMakeFile, /* 6 */
    TclpOpenFile, /* 7 */
    TclpGetPid, /* 8 */
    TclpCreateTempFile, /* 9 */
    0, /* 10 */
    TclGetAndDetachPids, /* 11 */
    0, /* 12 */
    0, /* 13 */






    0, /* 14 */



























    TclpCreateProcess, /* 15 */
    TclpIsAtty, /* 16 */
    TclUnixCopyFile, /* 17 */
    0, /* 18 */
    0, /* 19 */
    TclWinAddProcess, /* 20 */
    0, /* 21 */
    0, /* 22 */
    0, /* 23 */
    TclWinNoBackslash, /* 24 */
    0, /* 25 */
    0, /* 26 */
    TclWinFlushDirtyChannels, /* 27 */
    0, /* 28 */
    TclWinCPUID, /* 29 */
    TclUnixOpenTemporaryFile, /* 30 */


































};

static const TclPlatStubs tclPlatStubs = {
    TCL_STUB_MAGIC,
    0,

    0, /* 0 */
    Tcl_MacOSXOpenVersionedBundleResources, /* 1 */
    Tcl_MacOSXNotifierAddRunLoopMode, /* 2 */
    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
    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_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 */







|







726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
    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_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
    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 */
    0, /* 73 */
    0, /* 74 */
    0, /* 75 */
    TclBN_mp_signed_rsh, /* 76 */
    0, /* 77 */
    TclBN_mp_to_ubin, /* 78 */
    0, /* 79 */
    TclBN_mp_to_radix, /* 80 */
};

static const TclStubHooks tclStubHooks = {
    &tclPlatStubs,







|
|




|







778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
    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 */
    TclBN_mp_unpack, /* 71 */
    TclBN_mp_pack, /* 72 */
    0, /* 73 */
    0, /* 74 */
    0, /* 75 */
    TclBN_mp_signed_rsh, /* 76 */
    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
    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 */







<

<
<
<
<
<
<
<
<

<
<
<
<
<
<
<







808
809
810
811
812
813
814

815








816







817
818
819
820
821
822
823
    Tcl_Panic, /* 2 */
    Tcl_Alloc, /* 3 */
    Tcl_Free, /* 4 */
    Tcl_Realloc, /* 5 */
    Tcl_DbCkalloc, /* 6 */
    Tcl_DbCkfree, /* 7 */
    Tcl_DbCkrealloc, /* 8 */

    Tcl_CreateFileHandler, /* 9 */








    Tcl_DeleteFileHandler, /* 10 */







    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
    Tcl_GetDouble, /* 34 */
    Tcl_GetDoubleFromObj, /* 35 */
    0, /* 36 */
    Tcl_GetInt, /* 37 */
    Tcl_GetIntFromObj, /* 38 */
    Tcl_GetLongFromObj, /* 39 */
    Tcl_GetObjType, /* 40 */
    Tcl_GetStringFromObj, /* 41 */
    Tcl_InvalidateStringRep, /* 42 */
    Tcl_ListObjAppendList, /* 43 */
    Tcl_ListObjAppendElement, /* 44 */
    Tcl_ListObjGetElements, /* 45 */
    Tcl_ListObjIndex, /* 46 */
    Tcl_ListObjLength, /* 47 */
    Tcl_ListObjReplace, /* 48 */
    0, /* 49 */
    Tcl_NewByteArrayObj, /* 50 */
    Tcl_NewDoubleObj, /* 51 */
    0, /* 52 */
    Tcl_NewListObj, /* 53 */
    0, /* 54 */







|



|

|







840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
    Tcl_GetDouble, /* 34 */
    Tcl_GetDoubleFromObj, /* 35 */
    0, /* 36 */
    Tcl_GetInt, /* 37 */
    Tcl_GetIntFromObj, /* 38 */
    Tcl_GetLongFromObj, /* 39 */
    Tcl_GetObjType, /* 40 */
    TclGetStringFromObj, /* 41 */
    Tcl_InvalidateStringRep, /* 42 */
    Tcl_ListObjAppendList, /* 43 */
    Tcl_ListObjAppendElement, /* 44 */
    TclListObjGetElements, /* 45 */
    Tcl_ListObjIndex, /* 46 */
    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
    Tcl_AsyncMark, /* 74 */
    Tcl_AsyncReady, /* 75 */
    0, /* 76 */
    0, /* 77 */
    Tcl_BadChannelOption, /* 78 */
    Tcl_CallWhenDeleted, /* 79 */
    Tcl_CancelIdleCall, /* 80 */
    0, /* 81 */
    Tcl_CommandComplete, /* 82 */
    Tcl_Concat, /* 83 */
    Tcl_ConvertElement, /* 84 */
    Tcl_ConvertCountedElement, /* 85 */
    Tcl_CreateAlias, /* 86 */
    Tcl_CreateAliasObj, /* 87 */
    Tcl_CreateChannel, /* 88 */







|







880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
    Tcl_AsyncMark, /* 74 */
    Tcl_AsyncReady, /* 75 */
    0, /* 76 */
    0, /* 77 */
    Tcl_BadChannelOption, /* 78 */
    Tcl_CallWhenDeleted, /* 79 */
    Tcl_CancelIdleCall, /* 80 */
    Tcl_Close, /* 81 */
    Tcl_CommandComplete, /* 82 */
    Tcl_Concat, /* 83 */
    Tcl_ConvertElement, /* 84 */
    Tcl_ConvertCountedElement, /* 85 */
    Tcl_CreateAlias, /* 86 */
    Tcl_CreateAliasObj, /* 87 */
    Tcl_CreateChannel, /* 88 */
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
    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 */







<

<
<
<
<
<
<
<







966
967
968
969
970
971
972

973







974
975
976
977
978
979
980
    Tcl_GetCommandName, /* 160 */
    Tcl_GetErrno, /* 161 */
    Tcl_GetHostName, /* 162 */
    Tcl_GetInterpPath, /* 163 */
    Tcl_GetParent, /* 164 */
    Tcl_GetNameOfExecutable, /* 165 */
    Tcl_GetObjResult, /* 166 */

    Tcl_GetOpenFile, /* 167 */







    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
    Tcl_InputBuffered, /* 183 */
    Tcl_InterpDeleted, /* 184 */
    Tcl_IsSafe, /* 185 */
    Tcl_JoinPath, /* 186 */
    Tcl_LinkVar, /* 187 */
    0, /* 188 */
    Tcl_MakeFileChannel, /* 189 */
    Tcl_MakeSafe, /* 190 */
    Tcl_MakeTcpClientChannel, /* 191 */
    Tcl_Merge, /* 192 */
    Tcl_NextHashEntry, /* 193 */
    Tcl_NotifyChannel, /* 194 */
    Tcl_ObjGetVar2, /* 195 */
    Tcl_ObjSetVar2, /* 196 */
    Tcl_OpenCommandChannel, /* 197 */







|







989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
    Tcl_InputBuffered, /* 183 */
    Tcl_InterpDeleted, /* 184 */
    Tcl_IsSafe, /* 185 */
    Tcl_JoinPath, /* 186 */
    Tcl_LinkVar, /* 187 */
    0, /* 188 */
    Tcl_MakeFileChannel, /* 189 */
    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
    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 */
    0, /* 244 */
    0, /* 245 */
    0, /* 246 */
    0, /* 247 */
    Tcl_TraceVar2, /* 248 */
    Tcl_TranslateFileName, /* 249 */
    Tcl_Ungets, /* 250 */







|
|







1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
    Tcl_SetObjResult, /* 235 */
    Tcl_SetStdChannel, /* 236 */
    0, /* 237 */
    Tcl_SetVar2, /* 238 */
    Tcl_SignalId, /* 239 */
    Tcl_SignalMsg, /* 240 */
    Tcl_SourceRCFile, /* 241 */
    TclSplitList, /* 242 */
    TclSplitPath, /* 243 */
    0, /* 244 */
    0, /* 245 */
    0, /* 246 */
    0, /* 247 */
    Tcl_TraceVar2, /* 248 */
    Tcl_TranslateFileName, /* 249 */
    Tcl_Ungets, /* 250 */
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
    Tcl_GetThreadData, /* 305 */
    Tcl_GetVar2Ex, /* 306 */
    Tcl_InitNotifier, /* 307 */
    Tcl_MutexLock, /* 308 */
    Tcl_MutexUnlock, /* 309 */
    Tcl_ConditionNotify, /* 310 */
    Tcl_ConditionWait, /* 311 */
    Tcl_NumUtfChars, /* 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 */
    Tcl_UtfBackslash, /* 327 */
    Tcl_UtfFindFirst, /* 328 */
    Tcl_UtfFindLast, /* 329 */
    Tcl_UtfNext, /* 330 */
    Tcl_UtfPrev, /* 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 */
    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 */
    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 */
    0, /* 382 */
    Tcl_GetRange, /* 383 */
    0, /* 384 */
    Tcl_RegExpMatchObj, /* 385 */
    Tcl_SetNotifier, /* 386 */
    Tcl_GetAllocMutex, /* 387 */
    Tcl_GetChannelNames, /* 388 */
    Tcl_GetChannelNamesEx, /* 389 */
    Tcl_ProcObjCmd, /* 390 */
    Tcl_ConditionFinalize, /* 391 */







|












|
|



|
|




















|
















|
|









|
|

|
|







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
    Tcl_GetThreadData, /* 305 */
    Tcl_GetVar2Ex, /* 306 */
    Tcl_InitNotifier, /* 307 */
    Tcl_MutexLock, /* 308 */
    Tcl_MutexUnlock, /* 309 */
    Tcl_ConditionNotify, /* 310 */
    Tcl_ConditionWait, /* 311 */
    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 */
    TclUtfAtIndex, /* 325 */
    TclUtfCharComplete, /* 326 */
    Tcl_UtfBackslash, /* 327 */
    Tcl_UtfFindFirst, /* 328 */
    Tcl_UtfFindLast, /* 329 */
    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 */
    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 */
    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 */
    TclGetCharLength, /* 380 */
    TclGetUniChar, /* 381 */
    0, /* 382 */
    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
    Tcl_UntraceCommand, /* 427 */
    Tcl_AttemptAlloc, /* 428 */
    Tcl_AttemptDbCkalloc, /* 429 */
    Tcl_AttemptRealloc, /* 430 */
    Tcl_AttemptDbCkrealloc, /* 431 */
    Tcl_AttemptSetObjLength, /* 432 */
    Tcl_GetChannelThread, /* 433 */
    Tcl_GetUnicodeFromObj, /* 434 */
    0, /* 435 */
    0, /* 436 */
    Tcl_SubstObj, /* 437 */
    Tcl_DetachChannel, /* 438 */
    Tcl_IsStandardChannel, /* 439 */
    Tcl_FSCopyFile, /* 440 */
    Tcl_FSCopyDirectory, /* 441 */







|







1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
    Tcl_UntraceCommand, /* 427 */
    Tcl_AttemptAlloc, /* 428 */
    Tcl_AttemptDbCkalloc, /* 429 */
    Tcl_AttemptRealloc, /* 430 */
    Tcl_AttemptDbCkrealloc, /* 431 */
    Tcl_AttemptSetObjLength, /* 432 */
    Tcl_GetChannelThread, /* 433 */
    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
    Tcl_FSStat, /* 454 */
    Tcl_FSAccess, /* 455 */
    Tcl_FSOpenFileChannel, /* 456 */
    Tcl_FSGetCwd, /* 457 */
    Tcl_FSChdir, /* 458 */
    Tcl_FSConvertToPathType, /* 459 */
    Tcl_FSJoinPath, /* 460 */
    Tcl_FSSplitPath, /* 461 */
    Tcl_FSEqualPaths, /* 462 */
    Tcl_FSGetNormalizedPath, /* 463 */
    Tcl_FSJoinToPath, /* 464 */
    Tcl_FSGetInternalRep, /* 465 */
    Tcl_FSGetTranslatedPath, /* 466 */
    Tcl_FSEvalFile, /* 467 */
    Tcl_FSNewNativePath, /* 468 */







|







1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
    Tcl_FSStat, /* 454 */
    Tcl_FSAccess, /* 455 */
    Tcl_FSOpenFileChannel, /* 456 */
    Tcl_FSGetCwd, /* 457 */
    Tcl_FSChdir, /* 458 */
    Tcl_FSConvertToPathType, /* 459 */
    Tcl_FSJoinPath, /* 460 */
    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
    Tcl_AllocStatBuf, /* 490 */
    Tcl_Seek, /* 491 */
    Tcl_Tell, /* 492 */
    Tcl_ChannelWideSeekProc, /* 493 */
    Tcl_DictObjPut, /* 494 */
    Tcl_DictObjGet, /* 495 */
    Tcl_DictObjRemove, /* 496 */
    Tcl_DictObjSize, /* 497 */
    Tcl_DictObjFirst, /* 498 */
    Tcl_DictObjNext, /* 499 */
    Tcl_DictObjDone, /* 500 */
    Tcl_DictObjPutKeyList, /* 501 */
    Tcl_DictObjRemoveKeyList, /* 502 */
    Tcl_NewDictObj, /* 503 */
    Tcl_DbNewDictObj, /* 504 */







|







1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
    Tcl_AllocStatBuf, /* 490 */
    Tcl_Seek, /* 491 */
    Tcl_Tell, /* 492 */
    Tcl_ChannelWideSeekProc, /* 493 */
    Tcl_DictObjPut, /* 494 */
    Tcl_DictObjGet, /* 495 */
    Tcl_DictObjRemove, /* 496 */
    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
    Tcl_GetModificationTimeFromStat, /* 597 */
    Tcl_GetChangeTimeFromStat, /* 598 */
    Tcl_GetSizeFromStat, /* 599 */
    Tcl_GetBlocksFromStat, /* 600 */
    Tcl_GetBlockSizeFromStat, /* 601 */
    Tcl_SetEnsembleParameterList, /* 602 */
    Tcl_GetEnsembleParameterList, /* 603 */
    Tcl_ParseArgsObjv, /* 604 */
    Tcl_GetErrorLine, /* 605 */
    Tcl_SetErrorLine, /* 606 */
    Tcl_TransferResult, /* 607 */
    Tcl_InterpActive, /* 608 */
    Tcl_BackgroundException, /* 609 */
    Tcl_ZlibDeflate, /* 610 */
    Tcl_ZlibInflate, /* 611 */







|







1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
    Tcl_GetModificationTimeFromStat, /* 597 */
    Tcl_GetChangeTimeFromStat, /* 598 */
    Tcl_GetSizeFromStat, /* 599 */
    Tcl_GetBlocksFromStat, /* 600 */
    Tcl_GetBlockSizeFromStat, /* 601 */
    Tcl_SetEnsembleParameterList, /* 602 */
    Tcl_GetEnsembleParameterList, /* 603 */
    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
    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_InitStringRep, /* 637 */
    Tcl_FetchIntRep, /* 638 */
    Tcl_StoreIntRep, /* 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 */








































};

/* !END!: Do not edit above this line. */







|

|
|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



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
    Tcl_FSUnloadFile, /* 629 */
    Tcl_ZlibStreamSetCompressionDictionary, /* 630 */
    Tcl_OpenTcpServerEx, /* 631 */
    TclZipfs_Mount, /* 632 */
    TclZipfs_Unmount, /* 633 */
    TclZipfs_TclLibrary, /* 634 */
    TclZipfs_MountBuffer, /* 635 */
    Tcl_FreeInternalRep, /* 636 */
    Tcl_InitStringRep, /* 637 */
    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 */
    0, /* 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 */
    TclUnusedStubEntry, /* 688 */
};

/* !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
/*
 * 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.
 *
 * 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;


const TclStubs *tclStubsPtr = NULL;
const TclPlatStubs *tclPlatStubsPtr = NULL;
const TclIntStubs *tclIntStubsPtr = NULL;
const TclIntPlatStubs *tclIntPlatStubsPtr = NULL;


/*
 * Use our own ISDIGIT to avoid linking to libc on windows
 */

#define ISDIGIT(c) (((unsigned)((c)-'0')) <= 9)







|
|











>





>







1
2
3
4
5
6
7
8
9
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 © 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
MODULE_SCOPE const char *
Tcl_InitStubs(
    Tcl_Interp *interp,
    const char *version,
    int exact,
    int magic)
{
    Interp *iPtr = (Interp *) interp;
    const char *actualVersion = NULL;
    ClientData pkgData = NULL;
    const TclStubs *stubsPtr = iPtr->stubTable;




    /*
     * 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);
    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);
		return NULL;
	    }
	} else {
	    actualVersion = stubsPtr->tcl_PkgRequireEx(interp, "Tcl", version, 1, NULL);
	    if (actualVersion == NULL) {
		return NULL;
	    }
	}
    }
    if (((exact&0xFF00) < 0x900)) {
	/* We are running Tcl 8.x */
	stubsPtr = (TclStubs *)pkgData;



    }
    tclStubsPtr = stubsPtr;

    if (stubsPtr->hooks) {
	tclPlatStubsPtr = stubsPtr->hooks->tclPlatStubs;
	tclIntStubsPtr = stubsPtr->hooks->tclIntStubs;
	tclIntPlatStubsPtr = stubsPtr->hooks->tclIntPlatStubs;







|

|

>

>
>












|



















|



|








>
>
>







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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;
    const char *actualVersion = 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, 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, tclName, version, 1, NULL);
		return NULL;
	    }
	} else {
	    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
/*
 * 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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */



#undef STATIC_BUILD
#ifndef USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include "tclInt.h"
#ifdef TCL_WITH_EXTERNAL_TOMMATH
#   include "tommath.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
/*
 * 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 © 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
#include "tclInt.h"
#ifdef TCL_WITH_EXTERNAL_TOMMATH
#   include "tommath.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
#include "tclRegexp.h"

/*
 * Required for the TestChannelCmd and TestChannelEventCmd
 */
#include "tclIO.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 asynchronous handler
 * created by the "testasync" command".
 */

typedef struct TestAsyncHandler {
    int id;			/* Identifier for this handler. */







>
>














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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 "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
 * 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
                                 * test procedure */
};

TCL_DECLARE_MUTEX(asyncTestMutex)

static TestAsyncHandler *firstHandler = NULL;

/*







|
<







90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
 * 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 flags;			/* ORed combination of various bitfields. */

};

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

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;

/*







<
<
<
<
<
<
<







133
134
135
136
137
138
139







140
141
142
143
144
145
146

typedef struct {
    Tcl_Interp *interp;
    char *toUtfCmd;
    char *fromUtfCmd;
} TclEncoding;








/*
 * 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

/*
 * 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(







<

<







168
169
170
171
172
173
174

175

176
177
178
179
180
181
182

/*
 * Forward declarations for procedures defined later in this file:
 */

static int		AsyncHandlerProc(void *clientData,
			    Tcl_Interp *interp, int code);

static Tcl_ThreadCreateType AsyncThreadProc(void *);

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(
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222
223
224
225
226
static void		ExitProcEven(void *clientData);
static void		ExitProcOdd(void *clientData);
static Tcl_ObjCmdProc	GetTimesObjCmd;
static Tcl_ResolveCompiledVarProc	InterpCompiledVarResolver;
static void		MainLoop(void);
static Tcl_CmdProc	NoopCmd;
static Tcl_ObjCmdProc	NoopObjCmd;
static int		ObjTraceProc(void *clientData,
			    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 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;







|
<
<
<


|







>
|







208
209
210
211
212
213
214
215



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
static void		ExitProcEven(void *clientData);
static void		ExitProcOdd(void *clientData);
static Tcl_ObjCmdProc	GetTimesObjCmd;
static Tcl_ResolveCompiledVarProc	InterpCompiledVarResolver;
static void		MainLoop(void);
static Tcl_CmdProc	NoopCmd;
static Tcl_ObjCmdProc	NoopObjCmd;
static Tcl_CmdObjTraceProc ObjTraceProc;



static void		ObjTraceDeleteProc(void *clientData);
static void		PrintParse(Tcl_Interp *interp, Tcl_Parse *parsePtr);
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_ObjCmdProc2	Testcmdobj2ObjCmd;
static Tcl_ObjCmdProc	TestcmdinfoObjCmd;
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;
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
static Tcl_CmdProc	TestgetintCmd;
static Tcl_CmdProc	TestlongsizeCmd;
static Tcl_CmdProc	TestgetplatformCmd;
static Tcl_ObjCmdProc	TestgetvarfullnameCmd;
static Tcl_CmdProc	TestinterpdeleteCmd;
static Tcl_CmdProc	TestlinkCmd;
static Tcl_ObjCmdProc	TestlinkarrayCmd;

static Tcl_ObjCmdProc	TestlocaleCmd;
static Tcl_CmdProc	TestmainthreadCmd;
static Tcl_CmdProc	TestsetmainloopCmd;
static Tcl_CmdProc	TestexitmainloopCmd;
static Tcl_CmdProc	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 void		TestregexpXflags(const char *string,
			    size_t length, int *cflagsPtr, int *eflagsPtr);
static Tcl_ObjCmdProc	TestsaveresultCmd;
static void		TestsaveresultFree(void *blockPtr);
static Tcl_CmdProc	TestsetassocdataCmd;
static Tcl_CmdProc	TestsetCmd;
static Tcl_CmdProc	Testset2Cmd;
static Tcl_CmdProc	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 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;







>















<
<






|


|








<
<







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277


278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295


296
297
298
299
300
301
302
static Tcl_CmdProc	TestgetintCmd;
static Tcl_CmdProc	TestlongsizeCmd;
static Tcl_CmdProc	TestgetplatformCmd;
static Tcl_ObjCmdProc	TestgetvarfullnameCmd;
static Tcl_CmdProc	TestinterpdeleteCmd;
static Tcl_CmdProc	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	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 void		TestregexpXflags(const char *string,
			    size_t length, int *cflagsPtr, int *eflagsPtr);


static Tcl_CmdProc	TestsetassocdataCmd;
static Tcl_CmdProc	TestsetCmd;
static Tcl_CmdProc	Testset2Cmd;
static Tcl_CmdProc	TestseterrorcodeCmd;
static Tcl_ObjCmdProc	TestsetobjerrorcodeCmd;
static Tcl_CmdProc	TestsetplatformCmd;
static Tcl_CmdProc	TeststaticlibraryCmd;
static Tcl_CmdProc	TesttranslatefilenameCmd;
static Tcl_CmdProc	TestupvarCmd;
static Tcl_ObjCmdProc2	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 void		TestReport(const char *cmd, Tcl_Obj *arg1,
			    Tcl_Obj *arg2);


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;
319
320
321
322
323
324
325

326
327
328


329
330
331
332
333
334
335
336

337
338
339
340
341
342
343
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	TestFindFirstCmd;
static Tcl_ObjCmdProc	TestFindLastCmd;
static Tcl_ObjCmdProc	TestHashSystemHashCmd;



static Tcl_NRPostProc	NREUnwind_callback;
static Tcl_ObjCmdProc	TestNREUnwind;
static Tcl_ObjCmdProc	TestNRELevels;
static Tcl_ObjCmdProc	TestInterpResolverCmd;
#if defined(HAVE_CPUID) || defined(_WIN32)
static Tcl_ObjCmdProc	TestcpuidCmd;
#endif


static const Tcl_Filesystem testReportingFilesystem = {
    "reporting",
    sizeof(Tcl_Filesystem),
    TCL_FILESYSTEM_VERSION_1,
    TestReportInFilesystem, /* path in */
    TestReportDupInternalRep,







>



>
>





|


>







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
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(MAC_OSX_TCL)
static Tcl_ObjCmdProc	TestcpuidCmd;
#endif
static Tcl_ObjCmdProc	TestApplyLambdaObjCmd;

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
 *	the interp's result if an error occurs.
 *
 * Side effects:
 *	Depends on the startup script.
 *
 *----------------------------------------------------------------------
 */










































































int
Tcltest_Init(
    Tcl_Interp *interp)		/* Interpreter for application. */
{

    Tcl_Obj **objv, *objPtr;

    int objc, index;
    static const char *const specialOptions[] = {
	"-appinitprocerror", "-appinitprocdeleteinterp",
	"-appinitprocclosestderr", "-appinitprocsetrcfile", NULL
    };

    if (Tcl_InitStubs(interp, "8.5-", 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) {
	return TCL_ERROR;
    }

    /*
     * Create additional commands and math functions for testing Tcl.
     */

    Tcl_CreateObjCommand(interp, "gettimes", GetTimesObjCmd, 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,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetindexfromobjstruct",
	    TestGetIndexFromObjStructObjCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testasync", TestasyncCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testbumpinterpepoch",
	    TestbumpinterpepochObjCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testchannel", TestChannelCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testchannelevent", TestChannelEventCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, NULL,
	    NULL);


    Tcl_CreateCommand(interp, "testcmdinfo", TestcmdinfoCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testconcatobj", TestconcatobjCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testcreatecommand", TestcreatecommandCmd,
	    NULL, NULL);








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>

>
|





|



|






|
>
>
>
>
>
>
>
>
>
|
|














|
















>
>
|







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
 *	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 index;
    static const char *const specialOptions[] = {
	"-appinitprocerror", "-appinitprocdeleteinterp",
	"-appinitprocclosestderr", "-appinitprocsetrcfile", NULL
    };

    if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) {
	return TCL_ERROR;
    }
#ifndef TCL_WITH_EXTERNAL_TOMMATH
    if (Tcl_TomMath_InitStubs(interp, "8.7-") == NULL) {
	return TCL_ERROR;
    }
#endif
    if (Tcl_OOInitStubs(interp) == 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;
    }

    /*
     * Create additional commands and math functions for testing Tcl.
     */

    Tcl_CreateObjCommand(interp, "gettimes", GetTimesObjCmd, 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_CreateObjCommand2(interp, "testwrongnumargs", TestWrongNumArgsObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfilesystem", TestFilesystemObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsimplefilesystem", TestSimpleFilesystemObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetindexfromobjstruct",
	    TestGetIndexFromObjStructObjCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testasync", TestasyncCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testbumpinterpepoch",
	    TestbumpinterpepochObjCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testchannel", TestChannelCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testchannelevent", TestChannelEventCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testcmdtoken", TestcmdtokenCmd, NULL,
	    NULL);
    Tcl_CreateObjCommand2(interp, "testcmdobj2", Testcmdobj2ObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testcmdinfo", TestcmdinfoObjCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testcmdtrace", TestcmdtraceCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testconcatobj", TestconcatobjCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testcreatecommand", TestcreatecommandCmd,
	    NULL, NULL);
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
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetvarfullname",
	    TestgetvarfullnameCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testlink", TestlinkCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testlinkarray", TestlinkarrayCmd, NULL, NULL);

    Tcl_CreateObjCommand(interp, "testlocale", TestlocaleCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparseargs", TestparseargsCmd,NULL,NULL);
    Tcl_CreateObjCommand(interp, "testparser", TestparserObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testpreferstable", TestpreferstableObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testprint", TestprintObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsaveresult", TestsaveresultCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testservicemode", TestServiceModeCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testseterr", TestsetCmd,
	    INT2PTR(TCL_LEAVE_ERR_MSG), NULL);
    Tcl_CreateCommand(interp, "testset2", Testset2Cmd,
	    INT2PTR(TCL_LEAVE_ERR_MSG), NULL);
    Tcl_CreateCommand(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, "testfindfirst",
	    TestFindFirstCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "testfindlast",
	    TestFindLastCmd, NULL, NULL);


    Tcl_CreateCommand(interp, "testsetplatform", TestsetplatformCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsocket", TestSocketCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "teststaticpkg", TeststaticpkgCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testtranslatefilename",
	    TesttranslatefilenameCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testmainthread", TestmainthreadCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd,
	    NULL, NULL);
#if defined(HAVE_CPUID) || defined(_WIN32)
    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,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testsetencpath", TestsetencpathObjCmd,
	    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





    /*
     * Check for special options used in ../tests/main.test
     */

    objPtr = Tcl_GetVar2Ex(interp, "argv", NULL, TCL_GLOBAL_ONLY);
    if (objPtr != NULL) {







>


















<
<




















>
>




>
>




|










|









|

|













>
>
>
>







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
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgetvarfullname",
	    TestgetvarfullnameCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testinterpdelete", TestinterpdeleteCmd,
	    NULL, NULL);
    Tcl_CreateCommand(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, "testparseargs", TestparseargsCmd,NULL,NULL);
    Tcl_CreateObjCommand(interp, "testparser", TestparserObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparsevar", TestparsevarObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testparsevarname", TestparsevarnameObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testpreferstable", TestpreferstableObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testprint", TestprintObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testregexp", TestregexpObjCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testreturn", TestreturnObjCmd,
	    NULL, NULL);


    Tcl_CreateCommand(interp, "testservicemode", TestServiceModeCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsetassocdata", TestsetassocdataCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsetnoerr", TestsetCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testseterr", TestsetCmd,
	    INT2PTR(TCL_LEAVE_ERR_MSG), NULL);
    Tcl_CreateCommand(interp, "testset2", Testset2Cmd,
	    INT2PTR(TCL_LEAVE_ERR_MSG), NULL);
    Tcl_CreateCommand(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,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testsocket", TestSocketCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "teststaticlibrary", TeststaticlibraryCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testtranslatefilename",
	    TesttranslatefilenameCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testupvar", TestupvarCmd, NULL, NULL);
    Tcl_CreateCommand(interp, "testmainthread", TestmainthreadCmd, NULL,
	    NULL);
    Tcl_CreateCommand(interp, "testsetmainloop", TestsetmainloopCmd,
	    NULL, NULL);
    Tcl_CreateCommand(interp, "testexitmainloop", TestexitmainloopCmd,
	    NULL, NULL);
#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, "testapplylambda", TestApplyLambdaObjCmd,
	    NULL, NULL);
    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
	    case 2: {
		int mode;
		Tcl_UnregisterChannel(interp,
			Tcl_GetChannel(interp, "stderr", &mode));
		return TCL_ERROR;
	    }
	    case 3:
		if (objc-1) {
		    Tcl_SetVar2Ex(interp, "tcl_rcFileName", NULL, objv[1],
			    TCL_GLOBAL_ONLY);
		}
		return TCL_ERROR;
	    }
	}
    }







|







761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
	    case 2: {
		int mode;
		Tcl_UnregisterChannel(interp,
			Tcl_GetChannel(interp, "stderr", &mode));
		return TCL_ERROR;
	    }
	    case 3:
		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
 *----------------------------------------------------------------------
 */

int
Tcltest_SafeInit(
    Tcl_Interp *interp)		/* Interpreter for application. */
{


    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {













	return TCL_ERROR;
    }
    return Procbodytest_SafeInit(interp);
}

/*
 *----------------------------------------------------------------------







>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *----------------------------------------------------------------------
 */

int
Tcltest_SafeInit(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    Tcl_CmdInfo info;

    if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) {
	return TCL_ERROR;
    }
    if (Tcl_GetCommandInfo(interp, "::tcl::build-info", &info)) {
#if 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);
}

/*
 *----------------------------------------------------------------------
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
{
    TestAsyncHandler *asyncPtr, *prevPtr;
    int id, code;
    static int nextId = 1;

    if (argc < 2) {
	wrongNumArgs:
	Tcl_AppendResult(interp, "wrong # args", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	if (argc != 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->id = nextId;
	nextId++;
	asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc,
                                            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);
	    while (firstHandler != NULL) {
		asyncPtr = firstHandler;
		firstHandler = asyncPtr->nextPtr;
		Tcl_AsyncDelete(asyncPtr->handler);
		Tcl_Free(asyncPtr->command);
		Tcl_Free(asyncPtr);
	    }
            Tcl_MutexUnlock(&asyncTestMutex);
	    return TCL_OK;
	}
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
        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) {
	    goto wrongNumArgs;
	}
	if ((Tcl_GetInt(interp, argv[2], &id) != TCL_OK)
		|| (Tcl_GetInt(interp, argv[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_MutexUnlock(&asyncTestMutex);
	return code;
#if TCL_THREADS
    } else if (strcmp(argv[1], "marklater") == 0) {
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
        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_MutexUnlock(&asyncTestMutex);
		    return TCL_ERROR;
		}
		break;
	    }
	}
        Tcl_MutexUnlock(&asyncTestMutex);
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, int, mark, or marklater", 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. */
    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;
        }
    }
    Tcl_MutexUnlock(&asyncTestMutex);

    if (!asyncPtr) {
        /* 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);
    } 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);







|









|


|
<


|
|


|







|








|















|



















<







|







|






|


|

<
<
<
<
<
<







|












|
|
|
|




|
|









|







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
{
    TestAsyncHandler *asyncPtr, *prevPtr;
    int id, code;
    static int nextId = 1;

    if (argc < 2) {
	wrongNumArgs:
	Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	if (argc != 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->id = nextId;
	nextId++;
	asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc, INT2PTR(asyncPtr->id));

	asyncPtr->nextPtr = firstHandler;
	firstHandler = asyncPtr;
	Tcl_MutexUnlock(&asyncTestMutex);
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(asyncPtr->id));
    } else if (strcmp(argv[1], "delete") == 0) {
	if (argc == 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);
	    return TCL_OK;
	}
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
	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) {
	    goto wrongNumArgs;
	}
	if ((Tcl_GetInt(interp, argv[2], &id) != TCL_OK)
		|| (Tcl_GetInt(interp, argv[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_MutexUnlock(&asyncTestMutex);
	return code;

    } else if (strcmp(argv[1], "marklater") == 0) {
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &id) != TCL_OK) {
	    return TCL_ERROR;
	}
	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", (char *)NULL);
		    Tcl_MutexUnlock(&asyncTestMutex);
		    return TCL_ERROR;
		}
		break;
	    }
	}
	Tcl_MutexUnlock(&asyncTestMutex);
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, int, mark, or marklater", (char *)NULL);
	return TCL_ERROR;






    }
    return TCL_OK;
}

static int
AsyncHandlerProc(
    void *clientData,	/* If of TestAsyncHandler structure.
				 * 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;
	}
    }
    Tcl_MutexUnlock(&asyncTestMutex);

    if (!asyncPtr) {
	/* 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, 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
 *
 * 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;
        }
    }
    Tcl_MutexUnlock(&asyncTestMutex);
    Tcl_ExitThread(TCL_OK);
    TCL_THREAD_CREATE_RETURN;
}
#endif

static int
TestbumpinterpepochObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */







<











|
|
|
|
|





<







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
 *
 * Side effects:
 *	Invokes Tcl_AsyncMark on the handler
 *
 *----------------------------------------------------------------------
 */


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;
	}
    }
    Tcl_MutexUnlock(&asyncTestMutex);
    Tcl_ExitThread(TCL_OK);
    TCL_THREAD_CREATE_RETURN;
}


static int
TestbumpinterpepochObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
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
    iPtr->compileEpoch++;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *


































 * TestcmdinfoCmd --
 *
 *	This procedure implements the "testcmdinfo" command.  It is used to
 *	test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation and
 *	deletion.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Creates and deletes various commands and modifies their data.
 *
 *----------------------------------------------------------------------
 */

static int
TestcmdinfoCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{







    Tcl_CmdInfo info;



    if (argc != 3) {














	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option cmdName\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {














	Tcl_CreateCommand(interp, argv[2], CmdProc1, (void *) "original",
		CmdDelProc1);
    } else if (strcmp(argv[1], "delete") == 0) {


	Tcl_DStringInit(&delString);
	Tcl_DeleteCommand(interp, argv[2]);
	Tcl_DStringResult(interp, &delString);

    } else if (strcmp(argv[1], "get") == 0) {
	if (Tcl_GetCommandInfo(interp, argv[2], &info) ==0) {
	    Tcl_AppendResult(interp, "??", NULL);
	    return TCL_OK;
	}
	if (info.proc == CmdProc1) {
	    Tcl_AppendResult(interp, "CmdProc1", " ",
		    (char *) info.clientData, NULL);
	} else if (info.proc == CmdProc2) {
	    Tcl_AppendResult(interp, "CmdProc2", " ",
		    (char *) info.clientData, NULL);
	} else {
	    Tcl_AppendResult(interp, "unknown", NULL);
	}
	if (info.deleteProc == CmdDelProc1) {
	    Tcl_AppendResult(interp, " CmdDelProc1", " ",
		    (char *) info.deleteData, NULL);
	} else if (info.deleteProc == CmdDelProc2) {
	    Tcl_AppendResult(interp, " CmdDelProc2", " ",
		    (char *) info.deleteData, NULL);
	} else {
	    Tcl_AppendResult(interp, " unknown", NULL);
	}
	Tcl_AppendResult(interp, " ", info.namespacePtr->fullName, NULL);
	if (info.isNativeObjectProc) {


	    Tcl_AppendResult(interp, " nativeObjectProc", NULL);


	} else {
	    Tcl_AppendResult(interp, " stringProc", NULL);


	}
    } else if (strcmp(argv[1], "modify") == 0) {


	info.proc = CmdProc2;
	info.clientData = (void *) "new_command_data";
	info.objProc = NULL;
	info.objClientData = NULL;
	info.deleteProc = CmdDelProc2;
	info.deleteData = (void *) "new_delete_data";



	if (Tcl_SetCommandInfo(interp, argv[2], &info) == 0) {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(0));
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(1));
	}
    } else {

	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, get, or modify", NULL);
	return TCL_ERROR;
    }










    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);
    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);
    return TCL_OK;
}























static void
CmdDelProc1(
    void *clientData)	/* String to save. */
{
    Tcl_DStringInit(&delString);
    Tcl_DStringAppend(&delString, "CmdDelProc1 ", -1);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|















|


|
|

>
>
>
>
>
>
>

>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
<
>
>

|

>
|
|
|




|


|

|



|


|

|

|
|
>
>
|
>
>

|
>
>

<
>
>






>
>
>
|
|

|

|
>
|
<
|
|
>
>
>
>
>
>
>
>
>
>










|










|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    iPtr->compileEpoch++;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Testcmdobj2 --
 *
 *	Mock up to test the Tcl_CreateCommandObj2 functionality
 *
 * Results:
 *	Standard Tcl result.
 *
 * Side effects:
 *	Sets interpreter result to number of arguments, first arg, last arg.
 *
 *----------------------------------------------------------------------
 */

static int
Testcmdobj2ObjCmd(
    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;
}

/*
 *----------------------------------------------------------------------
 *
 * TestcmdinfoObjCmd --
 *
 *	This procedure implements the "testcmdinfo" command.  It is used to
 *	test Tcl_GetCommandInfo, Tcl_SetCommandInfo, and command creation and
 *	deletion.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Creates and deletes various commands and modifies their data.
 *
 *----------------------------------------------------------------------
 */

static int
TestcmdinfoObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    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 (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);

	    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);

	break;
    case CMDINFO_DELETE:
	Tcl_DStringInit(&delString);
	Tcl_DeleteCommand(interp, Tcl_GetString(objv[2]));
	Tcl_DStringResult(interp, &delString);
	break;
    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, (char *)NULL);
	} else if (info.proc == CmdProc2) {
	    Tcl_AppendResult(interp, "CmdProc2", " ",
		    (char *) info.clientData, (char *)NULL);
	} else {
	    Tcl_AppendResult(interp, "unknown", (char *)NULL);
	}
	if (info.deleteProc == CmdDelProc1) {
	    Tcl_AppendResult(interp, " CmdDelProc1", " ",
		    (char *) info.deleteData, (char *)NULL);
	} else if (info.deleteProc == CmdDelProc2) {
	    Tcl_AppendResult(interp, " CmdDelProc2", " ",
		    (char *) info.deleteData, (char *)NULL);
	} else {
	    Tcl_AppendResult(interp, " unknown", (char *)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_SetObjResult(interp, Tcl_ObjPrintf("Invalid isNativeObjectProc value %d",
		    info.isNativeObjectProc));
	    return TCL_ERROR;
	}

	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, Tcl_GetString(objv[2]), &info) == 0) {
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(0));
	} else {
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(1));
	}
	break;
    }


    return TCL_OK;
}

static int
CmdProc0(
    void *clientData,	/* String to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
{
    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, (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, (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);
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
static int
TestcmdtokenCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_Command token;
    int *l;
    char buf[30];

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option arg\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {

	token = Tcl_CreateCommand(interp, argv[2], CmdProc1,


		(void *) "original", NULL);



	sprintf(buf, "%p", (void *)token);
	Tcl_AppendResult(interp, buf, NULL);
    } else if (strcmp(argv[1], "name") == 0) {





	Tcl_Obj *objPtr;






	if (sscanf(argv[2], "%p", &l) != 1) {

	    Tcl_AppendResult(interp, "bad command token \"", argv[2],
		    "\"", NULL);
	    return TCL_ERROR;
	}




	objPtr = Tcl_NewObj();
	Tcl_GetCommandFullName(interp, (Tcl_Command) l, objPtr);

	Tcl_AppendElement(interp,
		Tcl_GetCommandName(interp, (Tcl_Command) l));
	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;
    }


    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestcmdtraceCmd --







|
|




|



>
|
>
>
|
>
>
>
|
|
|
>
>
>
>
>
|
>
>
>
>
|
>
|
>

|



>
>
>
|
|

|
|
|
|
|
|
|
|
|
>
>







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
static int
TestcmdtokenCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    TestCommandTokenRef *refPtr;
    int id;
    char buf[30];

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option arg\"", (char *)NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	refPtr = (TestCommandTokenRef *)Tcl_Alloc(sizeof(TestCommandTokenRef));
	refPtr->token = Tcl_CreateCommand(interp, argv[2], CmdProc0,
		refPtr, CmdDelProc0);
	refPtr->id = nextCommandTokenRefId;
	refPtr->value = "original";
	nextCommandTokenRefId++;
	refPtr->nextPtr = firstCommandTokenRef;
	firstCommandTokenRef = refPtr;
	snprintf(buf, sizeof(buf), "%d", refPtr->id);
	Tcl_AppendResult(interp, buf, (char *)NULL);
    } else {
	if (sscanf(argv[2], "%d", &id) != 1) {
	    Tcl_AppendResult(interp, "bad command token \"", argv[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 \"", argv[2],
		    "\"", (char *)NULL);
	    return TCL_ERROR;
	}

	if (strcmp(argv[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, name, or free", (char *)NULL);
	    return TCL_ERROR;
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestcmdtraceCmd --
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
    const char **argv)		/* Argument strings. */
{
    Tcl_DString buffer;
    int result;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option script\"", NULL);
	return TCL_ERROR;
    }

    if (strcmp(argv[1], "tracetest") == 0) {
	Tcl_DStringInit(&buffer);
	cmdTrace = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer);
	result = Tcl_EvalEx(interp, argv[2], -1, 0);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);
    } else if (strcmp(argv[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) {
	Interp *iPtr = (Interp *) interp;
	Tcl_DStringInit(&buffer);
	cmdTrace = Tcl_CreateTrace(interp, iPtr->numLevels + 4, CmdTraceProc,
		&buffer);
	result = Tcl_EvalEx(interp, argv[2], -1, 0);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);
    } else if (strcmp(argv[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,
		&deleteCalled, ObjTraceDeleteProc);
	result = Tcl_EvalEx(interp, argv[2], -1, 0);
	Tcl_DeleteTrace(interp, cmdTrace);
	if (!deleteCalled) {
	    Tcl_AppendResult(interp, "Delete wasn't called", NULL);
	    return TCL_ERROR;
	} else {
	    return result;
	}
    } else if (strcmp(argv[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);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), 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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static void
CmdTraceProc(







|






|


|












|





|


|














|


|










|


|






|







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
    const char **argv)		/* Argument strings. */
{
    Tcl_DString buffer;
    int result;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option script\"", (char *)NULL);
	return TCL_ERROR;
    }

    if (strcmp(argv[1], "tracetest") == 0) {
	Tcl_DStringInit(&buffer);
	cmdTrace = Tcl_CreateTrace(interp, 50000, CmdTraceProc, &buffer);
	result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (char *)NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);
    } else if (strcmp(argv[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], TCL_INDEX_NONE, 0);
    } else if (strcmp(argv[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], TCL_INDEX_NONE, 0);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    Tcl_AppendResult(interp, Tcl_DStringValue(&buffer), (char *)NULL);
	}
	Tcl_DeleteTrace(interp, cmdTrace);
	Tcl_DStringFree(&buffer);
    } else if (strcmp(argv[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,
		&deleteCalled, ObjTraceDeleteProc);
	result = Tcl_EvalEx(interp, argv[2], TCL_INDEX_NONE, 0);
	Tcl_DeleteTrace(interp, cmdTrace);
	if (!deleteCalled) {
	    Tcl_AppendResult(interp, "Delete wasn't called", (char *)NULL);
	    return TCL_ERROR;
	} else {
	    return result;
	}
    } else if (strcmp(argv[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], TCL_INDEX_NONE, 0);
	if (result == TCL_OK) {
	    Tcl_ResetResult(interp);
	    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", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static void
CmdTraceProc(
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
    Tcl_DeleteTrace(interp, cmdTrace);
}

static int
ObjTraceProc(
    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. */
{
    const char *word = Tcl_GetString(objv[0]);

    if (!strcmp(word, "Error")) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1));
	return TCL_ERROR;







|


|







1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
    Tcl_DeleteTrace(interp, cmdTrace);
}

static int
ObjTraceProc(
    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. */
{
    const char *word = Tcl_GetString(objv[0]);

    if (!strcmp(word, "Error")) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(command, -1));
	return TCL_ERROR;
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
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option\"", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateCommand(interp, "test_ns_basic::createdcommand",
		CreatedCommandProc, NULL, NULL);
    } else if (strcmp(argv[1], "delete") == 0) {
	Tcl_DeleteCommand(interp, "test_ns_basic::createdcommand");
    } else if (strcmp(argv[1], "create2") == 0) {
	Tcl_CreateCommand(interp, "value:at:",
		CreatedCommandProc2, NULL, NULL);
    } else if (strcmp(argv[1], "delete2") == 0) {
	Tcl_DeleteCommand(interp, "value:at:");
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[1],
		"\": must be create, delete, create2, or delete2", 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_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);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "CreatedCommandProc in ",
	    info.namespacePtr->fullName, 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_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);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "CreatedCommandProc2 in ",
	    info.namespacePtr->fullName, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestdcallCmd --







|














|



















|



|
















|



|







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
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option\"", (char *)NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateCommand(interp, "test_ns_basic::createdcommand",
		CreatedCommandProc, NULL, NULL);
    } else if (strcmp(argv[1], "delete") == 0) {
	Tcl_DeleteCommand(interp, "test_ns_basic::createdcommand");
    } else if (strcmp(argv[1], "create2") == 0) {
	Tcl_CreateCommand(interp, "value:at:",
		CreatedCommandProc2, NULL, NULL);
    } else if (strcmp(argv[1], "delete2") == 0) {
	Tcl_DeleteCommand(interp, "value:at:");
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[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_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",
		(char *)NULL);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "CreatedCommandProc in ",
	    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_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",
		(char *)NULL);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "CreatedCommandProc2 in ",
	    info.namespacePtr->fullName, (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestdcallCmd --
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    DelCmd *dPtr;
    Tcl_Interp *child;

    if (argc != 4) {
	Tcl_AppendResult(interp, "wrong # args", NULL);
	return TCL_ERROR;
    }

    child = Tcl_GetChild(interp, argv[1]);
    if (child == NULL) {
	return TCL_ERROR;
    }







|







1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    DelCmd *dPtr;
    Tcl_Interp *child;

    if (argc != 4) {
	Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
	return TCL_ERROR;
    }

    child = Tcl_GetChild(interp, argv[1]);
    if (child == NULL) {
	return TCL_ERROR;
    }
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
    void *clientData,	/* String result to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
{
    DelCmd *dPtr = (DelCmd *) clientData;

    Tcl_AppendResult(interp, dPtr->deleteCmd, 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_ResetResult(dPtr->interp);
    Tcl_Free(dPtr->deleteCmd);
    Tcl_Free(dPtr);
}

/*
 *----------------------------------------------------------------------







|











|







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
    void *clientData,	/* String result to return. */
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*argc*/,
    TCL_UNUSED(const char **) /*argv*/)
{
    DelCmd *dPtr = (DelCmd *) clientData;

    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, TCL_INDEX_NONE, 0);
    Tcl_ResetResult(dPtr->interp);
    Tcl_Free(dPtr->deleteCmd);
    Tcl_Free(dPtr);
}

/*
 *----------------------------------------------------------------------
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key\"", NULL);
	return TCL_ERROR;
    }
    Tcl_DeleteAssocData(interp, argv[1]);
    return TCL_OK;
}

/*







|







1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key\"", (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_DeleteAssocData(interp, argv[1]);
    return TCL_OK;
}

/*
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
static int
TestdoubledigitsObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp* interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj* const objv[])	/* Parameter vector */
{
    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;
    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)) {
	    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) {
	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));
    strObj = Tcl_NewStringObj(signum ? "-" : "+", 1);
    Tcl_ListObjAppendElement(NULL, retval, strObj);
    Tcl_SetObjResult(interp, retval);
    return TCL_OK;
}

/*







|


















|
|










|
|





|
|
|















|







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
static int
TestdoubledigitsObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp* interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj* const objv[])	/* Parameter vector */
{
    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;
    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_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) {
	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_NewWideIntObj(decpt));
    strObj = Tcl_NewStringObj(signum ? "-" : "+", 1);
    Tcl_ListObjAppendElement(NULL, retval, strObj);
    Tcl_SetObjResult(interp, retval);
    return TCL_OK;
}

/*
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int count;

    if (argc < 2) {
	wrongNumArgs:
	Tcl_AppendResult(interp, "wrong # args", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "append") == 0) {
	if (argc != 4) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[3], &count) != TCL_OK) {







|







1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int count;

    if (argc < 2) {
	wrongNumArgs:
	Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "append") == 0) {
	if (argc != 4) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[3], &count) != TCL_OK) {
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
	}
	Tcl_SetResult(interp, Tcl_DStringValue(&dstring), TCL_VOLATILE);
    } else if (strcmp(argv[1], "gresult") == 0) {
	if (argc != 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) {
	    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) {
	    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],
		    "\": must be staticsmall, staticlarge, free, or special",
		    NULL);
	    return TCL_ERROR;
	}
	Tcl_DStringGetResult(interp, &dstring);
    } else if (strcmp(argv[1], "length") == 0) {

	if (argc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(Tcl_DStringLength(&dstring)));
    } else if (strcmp(argv[1], "result") == 0) {
	if (argc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_DStringResult(interp, &dstring);





    } else if (strcmp(argv[1], "trunc") == 0) {
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &count) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_DStringSetLength(&dstring, count);
    } else if (strcmp(argv[1], "start") == 0) {
	if (argc != 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);
	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(

    void *blockPtr			/* Block to free. */



) {
    Tcl_Free(((char *)blockPtr) - 16);
}

























































































































































































































/*
 *----------------------------------------------------------------------
 *
 * TestencodingCmd --
 *
 *	This procedure implements the "testencoding" command.  It is used







|

|











|








|





>
>
>
>
>















|
|











>

>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	}
	Tcl_SetResult(interp, Tcl_DStringValue(&dstring), TCL_VOLATILE);
    } else if (strcmp(argv[1], "gresult") == 0) {
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	if (strcmp(argv[2], "staticsmall") == 0) {
	    Tcl_AppendResult(interp, "short", (char *)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", (char *)NULL);
	} else if (strcmp(argv[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) {
	    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],
		    "\": must be staticsmall, staticlarge, free, or special",
		    (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_DStringGetResult(interp, &dstring);
    } else if (strcmp(argv[1], "length") == 0) {

	if (argc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(Tcl_DStringLength(&dstring)));
    } else if (strcmp(argv[1], "result") == 0) {
	if (argc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_DStringResult(interp, &dstring);
    } else if (strcmp(argv[1], "toobj") == 0) {
	if (argc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_SetObjResult(interp, Tcl_DStringToObj(&dstring));
    } else if (strcmp(argv[1], "trunc") == 0) {
	if (argc != 3) {
	    goto wrongNumArgs;
	}
	if (Tcl_GetInt(interp, argv[2], &count) != TCL_OK) {
	    return TCL_ERROR;
	}
	Tcl_DStringSetLength(&dstring, count);
    } else if (strcmp(argv[1], "start") == 0) {
	if (argc != 2) {
	    goto wrongNumArgs;
	}
	Tcl_DStringStartSublist(&dstring);
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[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 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},
	{"profiletcl8", TCL_ENCODING_PROFILE_TCL8},
	{"profilestrict", TCL_ENCODING_PROFILE_STRICT},
	{"profilereplace", 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_SetResult(interp,
		"Tcl_ExternalToUtf wrote past output buffer",
		TCL_STATIC);
	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
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
TestencodingObjCmd(
    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;
    const char *string;
    TclEncoding *encodingPtr;
    static const char *const optionStrings[] = {
	"create",	"delete",	NULL
    };
    enum options {
	ENC_CREATE,	ENC_DELETE

    };





    if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0,
	    &index) != TCL_OK) {
	return TCL_ERROR;
    }

    switch ((enum options) index) {
    case ENC_CREATE: {
	Tcl_EncodingType type;

	if (objc != 5) {

	    return TCL_ERROR;
	}
	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);







|



|


|
>
|
>
>
>
>






|




>


|







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
TestencodingObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Encoding encoding;
    Tcl_Size length;
    const char *string;
    TclEncoding *encodingPtr;
    static const char *const optionStrings[] = {
	"create", "delete", "nullength", "Tcl_ExternalToUtf", "Tcl_UtfToExternal", NULL
    };
    enum options {
	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 (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->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
	    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 */
	break;



















    }
    return TCL_OK;
}

static int
EncodingToUtfProc(
    void *clientData,	/* TclEncoding structure. */







|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    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 */
	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
    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);

    len = strlen(Tcl_GetStringResult(encodingPtr->interp));
    if (len > dstLen) {
	len = dstLen;
    }
    memcpy(dst, Tcl_GetStringResult(encodingPtr->interp), len);
    Tcl_ResetResult(encodingPtr->interp);







|







2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
    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, 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
    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);

    len = strlen(Tcl_GetStringResult(encodingPtr->interp));
    if (len > dstLen) {
	len = dstLen;
    }
    memcpy(dst, Tcl_GetStringResult(encodingPtr->interp), len);
    Tcl_ResetResult(encodingPtr->interp);







|







2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
    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, 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);
1995
1996
1997
1998
1999
2000
2001
2002

2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
static int
TestevalexObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int length, flags;

    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);
	    return TCL_ERROR;
	}
	flags = TCL_EVAL_GLOBAL;
    } else if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "script ?global?");
	return TCL_ERROR;
    }







|
>







|







2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
static int
TestevalexObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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", (char *)NULL);
	    return TCL_ERROR;
	}
	flags = TCL_EVAL_GLOBAL;
    } else if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "script ?global?");
	return TCL_ERROR;
    }
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
	"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[] = {
				/* Interpretation of the chosen position */
	TCL_QUEUE_HEAD,
	TCL_QUEUE_TAIL,
	TCL_QUEUE_MARK
    };
    TestEvent *ev;		/* Event to be queued */








|







2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
	"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 int posNum[] = {
				/* Interpretation of the chosen position */
	TCL_QUEUE_HEAD,
	TCL_QUEUE_TAIL,
	TCL_QUEUE_MARK
    };
    TestEvent *ev;		/* Event to be queued */

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
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int value;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" create|delete value\"", NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
		INT2PTR(value));
    } else if (strcmp(argv[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);
	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));
    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));
    len = strlen(buf);
    if (len != (int) write(1, buf, len)) {
	Tcl_Panic("ExitProcEven: unable to write to stdout");
    }
}

/*







|













|












|













|







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
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int value;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" create|delete value\"", (char *)NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetInt(interp, argv[2], &value) != TCL_OK) {
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	Tcl_CreateExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
		INT2PTR(value));
    } else if (strcmp(argv[1], "delete") == 0) {
	Tcl_DeleteExitHandler((value & 1) ? ExitProcOdd : ExitProcEven,
		INT2PTR(value));
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[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;

    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;

    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");
    }
}

/*
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
{
    long exprResult;
    char buf[4 + TCL_INTEGER_SPACE];
    int result;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" expression\"", NULL);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "This is a result", NULL);
    result = Tcl_ExprLong(interp, argv[1], &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    sprintf(buf, ": %ld", exprResult);
    Tcl_AppendResult(interp, buf, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprlongobjCmd --







|


|




|
|







2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
{
    long exprResult;
    char buf[4 + TCL_INTEGER_SPACE];
    int result;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" expression\"", (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "This is a result", (char *)NULL);
    result = Tcl_ExprLong(interp, argv[1], &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    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
    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);
    result = Tcl_ExprLongObj(interp, objv[1], &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    sprintf(buf, ": %ld", exprResult);
    Tcl_AppendResult(interp, buf, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprdoubleCmd --







|




|
|







2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
    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", (char *)NULL);
    result = Tcl_ExprLongObj(interp, objv[1], &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    snprintf(buf, sizeof(buf), ": %ld", exprResult);
    Tcl_AppendResult(interp, buf, (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprdoubleCmd --
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
{
    double exprResult;
    char buf[4 + TCL_DOUBLE_SPACE];
    int result;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" expression\"", NULL);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "This is a result", NULL);
    result = Tcl_ExprDouble(interp, argv[1], &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    strcpy(buf, ": ");
    Tcl_PrintDouble(interp, exprResult, buf+2);
    Tcl_AppendResult(interp, buf, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprdoubleobjCmd --







|


|






|







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
{
    double exprResult;
    char buf[4 + TCL_DOUBLE_SPACE];
    int result;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" expression\"", (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, "This is a result", (char *)NULL);
    result = Tcl_ExprDouble(interp, argv[1], &exprResult);
    if (result != TCL_OK) {
	return result;
    }
    strcpy(buf, ": ");
    Tcl_PrintDouble(interp, exprResult, buf+2);
    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
    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);
    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);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprstringCmd --







|






|







2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
    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", (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, (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestexprstringCmd --
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" expression\"", NULL);
	return TCL_ERROR;
    }
    return Tcl_ExprString(interp, argv[1]);
}

/*
 *----------------------------------------------------------------------







|







3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" expression\"", (char *)NULL);
	return TCL_ERROR;
    }
    return Tcl_ExprString(interp, argv[1]);
}

/*
 *----------------------------------------------------------------------
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
	/* 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);
	    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);
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, contents);
    if (objc == 2) {
	/*
	 * If we are creating a link, this will actually just







|








|







3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
	/* 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), (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), (char *)NULL);
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, contents);
    if (objc == 2) {
	/*
	 * If we are creating a link, this will actually just
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
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    char *res;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key\"", NULL);
	return TCL_ERROR;
    }
    res = (char *) Tcl_GetAssocData(interp, argv[1], NULL);
    if (res != NULL) {
	Tcl_AppendResult(interp, res, NULL);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestgetplatformCmd --
 *
 *	This procedure implements the "testgetplatform" command. It is
 *	used to retrievel the value of the tclPlatform global variable.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *







|




|










|







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
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    char *res;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key\"", (char *)NULL);
	return TCL_ERROR;
    }
    res = (char *) Tcl_GetAssocData(interp, argv[1], NULL);
    if (res != NULL) {
	Tcl_AppendResult(interp, res, (char *)NULL);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestgetplatformCmd --
 *
 *	This procedure implements the "testgetplatform" command. It is
 *	used to retrieve the value of the tclPlatform global variable.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
    static const char *const platformStrings[] = { "unix", "mac", "windows" };
    TclPlatformType *platform;

    platform = TclGetPlatform();

    if (argc != 1) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		NULL);
	return TCL_ERROR;
    }

    Tcl_AppendResult(interp, platformStrings[*platform], NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestinterpdeleteCmd --







|



|







3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
    static const char *const platformStrings[] = { "unix", "mac", "windows" };
    TclPlatformType *platform;

    platform = TclGetPlatform();

    if (argc != 1) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		(char *)NULL);
	return TCL_ERROR;
    }

    Tcl_AppendResult(interp, platformStrings[*platform], (char *)NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestinterpdeleteCmd --
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_Interp *childToDelete;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" path\"", NULL);
	return TCL_ERROR;
    }
    childToDelete = Tcl_GetChild(interp, argv[1]);
    if (childToDelete == NULL) {
	return TCL_ERROR;
    }
    Tcl_DeleteInterp(childToDelete);







|







3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    Tcl_Interp *childToDelete;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" path\"", (char *)NULL);
	return TCL_ERROR;
    }
    childToDelete = Tcl_GetChild(interp, argv[1]);
    if (childToDelete == NULL) {
	return TCL_ERROR;
    }
    Tcl_DeleteInterp(childToDelete);
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
    char buffer[2*TCL_DOUBLE_SPACE];
    int writable, flag;
    Tcl_Obj *tmp;

    if (argc < 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);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	if (argc != 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);
	    return TCL_ERROR;
	}
	if (created) {
	    Tcl_UnlinkVar(interp, "int");
	    Tcl_UnlinkVar(interp, "real");
	    Tcl_UnlinkVar(interp, "bool");
	    Tcl_UnlinkVar(interp, "string");







|







|







3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
    char buffer[2*TCL_DOUBLE_SPACE];
    int writable, flag;
    Tcl_Obj *tmp;

    if (argc < 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?\"", (char *)NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "create") == 0) {
	if (argc != 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\"", (char *)NULL);
	    return TCL_ERROR;
	}
	if (created) {
	    Tcl_UnlinkVar(interp, "int");
	    Tcl_UnlinkVar(interp, "real");
	    Tcl_UnlinkVar(interp, "bool");
	    Tcl_UnlinkVar(interp, "string");
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
	    Tcl_UnlinkVar(interp, "float");
	    Tcl_UnlinkVar(interp, "uwide");
	}
	created = 1;
	if (Tcl_GetBoolean(interp, argv[2], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "wide", &wideVar,
			TCL_LINK_WIDE_INT | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[7], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	    return TCL_ERROR;
	}
	flag = (writable != 0) ? 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) {
	Tcl_UnlinkVar(interp, "int");







|







|







|







|







|

|





|







|







|







|







|







|







|







|







|







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
	    Tcl_UnlinkVar(interp, "float");
	    Tcl_UnlinkVar(interp, "uwide");
	}
	created = 1;
	if (Tcl_GetBoolean(interp, argv[2], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	flag = writable ? 0 : TCL_LINK_READ_ONLY;
	if (Tcl_LinkVar(interp, "wide", &wideVar,
		TCL_LINK_WIDE_INT | flag) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[7], &writable) != TCL_OK) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	    return TCL_ERROR;
	}
	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) {
	Tcl_UnlinkVar(interp, "int");
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
	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);
	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);

	Tcl_AppendElement(interp, Tcl_GetString(tmp));
	Tcl_DecrRefCount(tmp);
    } else if (strcmp(argv[1], "set") == 0) {
	int v;

	if (argc != 16) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " ", argv[1],
		    " intValue realValue boolValue stringValue wideValue"
		    " charValue ucharValue shortValue ushortValue uintValue"
		    " longValue ulongValue floatValue uwideValue\"", NULL);
	    return TCL_ERROR;
	}
	if (argv[2][0] != 0) {
	    if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	}







>
>
>
>
>
>
>
>
>
|




>
>
>
>
>
>
>
|
>










|







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
	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);
#ifdef TCL_WIDE_INT_IS_LONG
	if (ulongVar > WIDE_MAX) {
		mp_int bignumValue;
		if (mp_init_u64(&bignumValue, ulongVar) != MP_OKAY) {
		    Tcl_Panic("%s: memory overflow", "Tcl_SetWideUIntObj");
		}
		tmp = Tcl_NewBignumObj(&bignumValue);
	} else
#endif /* TCL_WIDE_INT_IS_LONG */
	tmp = Tcl_NewWideIntObj((Tcl_WideInt)ulongVar);
	Tcl_AppendElement(interp, Tcl_GetString(tmp));
	Tcl_DecrRefCount(tmp);
	Tcl_PrintDouble(NULL, (double)floatVar, buffer);
	Tcl_AppendElement(interp, buffer);
	if (uwideVar > WIDE_MAX) {
		mp_int bignumValue;
		if (mp_init_u64(&bignumValue, uwideVar) != MP_OKAY) {
		    Tcl_Panic("%s: memory overflow", "Tcl_SetWideUIntObj");
		}
		tmp = Tcl_NewBignumObj(&bignumValue);
	} else {
	    tmp = Tcl_NewWideIntObj((Tcl_WideInt)uwideVar);
	}
	Tcl_AppendElement(interp, Tcl_GetString(tmp));
	Tcl_DecrRefCount(tmp);
    } else if (strcmp(argv[1], "set") == 0) {
	int v;

	if (argc != 16) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " ", argv[1],
		    " intValue realValue boolValue stringValue wideValue"
		    " charValue ucharValue shortValue ushortValue uintValue"
		    " longValue ulongValue floatValue uwideValue\"", (char *)NULL);
	    return TCL_ERROR;
	}
	if (argv[2][0] != 0) {
	    if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	}
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
	int v;

	if (argc != 16) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " ", argv[1],
		    " intValue realValue boolValue stringValue wideValue"
		    " charValue ucharValue shortValue ushortValue uintValue"
		    " longValue ulongValue floatValue uwideValue\"", NULL);
	    return TCL_ERROR;
	}
	if (argv[2][0] != 0) {
	    if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	    Tcl_UpdateLinkedVar(interp, "int");







|







3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
	int v;

	if (argc != 16) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"",
		    argv[0], " ", argv[1],
		    " intValue realValue boolValue stringValue wideValue"
		    " charValue ucharValue shortValue ushortValue uintValue"
		    " longValue ulongValue floatValue uwideValue\"", (char *)NULL);
	    return TCL_ERROR;
	}
	if (argv[2][0] != 0) {
	    if (Tcl_GetInt(interp, argv[2], &intVar) != TCL_OK) {
		return TCL_ERROR;
	    }
	    Tcl_UpdateLinkedVar(interp, "int");
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
	    }
	    Tcl_DecrRefCount(tmp);
	    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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|







3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
	    }
	    Tcl_DecrRefCount(tmp);
	    uwideVar = (Tcl_WideUInt) w;
	    Tcl_UpdateLinkedVar(interp, "uwide");
	}
    } else {
	Tcl_AppendResult(interp, "bad option \"", argv[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
 *
 *----------------------------------------------------------------------
 */

static int
TestlinkarrayCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,         /* Current interpreter. */
    int objc,                   /* Number of arguments. */
    Tcl_Obj *const objv[])      /* Argument objects. */
{
    static const char *LinkOption[] = {
        "update", "remove", "create", NULL
    };
    enum LinkOptionEnum { LINK_UPDATE, LINK_REMOVE, LINK_CREATE };
    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;

    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) {
    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++) {







|
|



|

|












|
>











|







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
 *
 *----------------------------------------------------------------------
 */

static int
TestlinkarrayCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,	 /* Current interpreter. */
    int objc,		   /* Number of arguments. */
    Tcl_Obj *const objv[])      /* Argument objects. */
{
    static const char *LinkOption[] = {
	"update", "remove", "create", NULL
    };
    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 typeIndex, readonly, i, size;
    Tcl_Size 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 (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++) {
3293
3294
3295
3296
3297
3298
3299


























































































































































3300
3301
3302
3303
3304
3305
3306
    }
    return TCL_OK;

  wrongArgs:
    Tcl_WrongNumArgs(interp, 2, objv, "?-readonly? type size name ?address?");
    return TCL_ERROR;
}



























































































































































/*
 *----------------------------------------------------------------------
 *
 * TestlocaleCmd --
 *
 *	This procedure implements the "testlocale" command.  It is used







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    }
    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
3405
3406
3407
3408
3409
3410
3411

3412
3413
3414
3415
3416
3417
3418
3419
TestparserObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *script;

    int length, dummy;
    Tcl_Parse parse;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "script length");
	return TCL_ERROR;
    }
    script = Tcl_GetStringFromObj(objv[1], &dummy);







>
|







4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
TestparserObjCmd(
    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;
    Tcl_Parse parse;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "script length");
	return TCL_ERROR;
    }
    script = Tcl_GetStringFromObj(objv[1], &dummy);
3461
3462
3463
3464
3465
3466
3467

3468
3469
3470
3471
3472
3473
3474
3475
TestexprparserObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *script;

    int length, dummy;
    Tcl_Parse parse;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "expr length");
	return TCL_ERROR;
    }
    script = Tcl_GetStringFromObj(objv[1], &dummy);







>
|







4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
TestexprparserObjCmd(
    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;
    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
    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;

    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));
    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:







|












|







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
    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;
    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_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
	    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_ListObjAppendElement(NULL, objPtr,

	    Tcl_NewStringObj(parsePtr->commandStart + parsePtr->commandSize,
	    -1));
}

/*
 *----------------------------------------------------------------------
 *
 * TestparsevarObjCmd --
 *







|


>

|







4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
	    break;
	}
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj(typeString, -1));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewStringObj(tokenPtr->start, tokenPtr->size));
	Tcl_ListObjAppendElement(NULL, objPtr,
		Tcl_NewWideIntObj(tokenPtr->numComponents));
    }
    Tcl_ListObjAppendElement(NULL, objPtr,
	    parsePtr->commandStart ?
	    Tcl_NewStringObj(parsePtr->commandStart + parsePtr->commandSize,
	    TCL_INDEX_NONE) : Tcl_NewObj());
}

/*
 *----------------------------------------------------------------------
 *
 * TestparsevarObjCmd --
 *
3649
3650
3651
3652
3653
3654
3655
3656

3657
3658
3659
3660
3661
3662
3663
TestparsevarnameObjCmd(
    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;

    Tcl_Parse parse;

    if (objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "script length append");
	return TCL_ERROR;
    }
    script = Tcl_GetStringFromObj(objv[1], &dummy);







|
>







4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
TestparsevarnameObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    const char *script;
    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);
3743
3744
3745
3746
3747
3748
3749

3750
3751
3752

3753
3754
3755
3756
3757
3758

3759
3760
3761
3762
3763
3764
3765
3766
    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;


    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "format wideint");

    }

    if (objc > 1) {
	Tcl_GetWideIntFromObj(interp, objv[2], &argv1);
    }
    argv2 = (size_t)argv1;

    Tcl_SetObjResult(interp, Tcl_ObjPrintf(Tcl_GetString(objv[1]), argv1, argv2, argv2));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestregexpObjCmd --







>

|

>


<
|
<

>
|







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
    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 != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "format wideint");
	return TCL_OK;
    }


    Tcl_GetWideIntFromObj(interp, objv[2], &argv1);

    argv2 = (size_t)argv1;
    argv3 = (long)argv1;
    Tcl_SetObjResult(interp, Tcl_ObjPrintf(Tcl_GetString(objv[1]), argv1, argv2, argv3, argv3));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestregexpObjCmd --
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
static int
TestregexpObjCmd(
    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 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
    };

    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) {
	case REGEXP_INDICES:
	    indices = 1;
	    break;
	case REGEXP_NOCASE:
	    cflags |= REG_ICASE;
	    break;
	case REGEXP_ABOUT:







|
|
















|









<









|







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
static int
TestregexpObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, indices, match, about;
    Tcl_Size stringLength, 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;


	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 (index) {
	case REGEXP_INDICES:
	    indices = 1;
	    break;
	case REGEXP_NOCASE:
	    cflags |= REG_ICASE;
	    break;
	case REGEXP_ABOUT:
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
    }
    if (match == 0) {
	/*
	 * Set the interpreter's object result to an integer object w/
	 * value 0.
	 */

	Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
	if (objc > 2 && (cflags&REG_EXPECT) && indices) {
	    const char *varName;
	    const char *value;
	    size_t 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));
	    value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
	    if (value == NULL) {
		Tcl_AppendResult(interp, "couldn't set variable \"",
			varName, "\"", 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);
	    value = Tcl_SetVar2(interp, varName, NULL, resinfo, 0);
	    if (value == NULL) {
		Tcl_AppendResult(interp, "couldn't set variable \"",
			varName, "\"", 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_Obj *newPtr, *varPtr, *valuePtr;

	varPtr = objv[i];
	ii = ((cflags&REG_EXPECT) && i == objc-1) ? TCL_INDEX_NONE : (size_t)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;







|



|



|
|



|









|



|
















|



|







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
    }
    if (match == 0) {
	/*
	 * Set the interpreter's object result to an integer object w/
	 * value 0.
	 */

	Tcl_SetWideIntObj(Tcl_GetObjResult(interp), 0);
	if (objc > 2 && (cflags&REG_EXPECT) && indices) {
	    const char *varName;
	    const char *value;
	    Tcl_Size start, end;
	    char resinfo[TCL_INTEGER_SPACE * 2];

	    varName = Tcl_GetString(objv[2]);
	    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, "\"", (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]);
	    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, "\"", (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++) {
	Tcl_Size start, end;
	Tcl_Obj *newPtr, *varPtr, *valuePtr;

	varPtr = objv[i];
	ii = ((cflags&REG_EXPECT) && i == objc-1) ? TCL_INDEX_NONE : (Tcl_Size)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
	     * instead of the first character after the match.
	     */

	    if (end != TCL_INDEX_NONE) {
		end--;
	    }

	    objs[0] = Tcl_NewIntObj(start);
	    objs[1] = Tcl_NewIntObj(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) {
		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);
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * TestregexpXflags --







|
|






|
















|







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
	     * instead of the first character after the match.
	     */

	    if (end != TCL_INDEX_NONE) {
		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 || 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_SetWideIntObj(Tcl_GetObjResult(interp), 1);
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * TestregexpXflags --
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
    const char **argv)		/* Argument strings. */
{
    char *buf, *oldData;
    Tcl_InterpDeleteProc *procPtr;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key data_item\"", NULL);
	return TCL_ERROR;
    }

    buf = (char *)Tcl_Alloc(strlen(argv[2]) + 1);
    strcpy(buf, argv[2]);

    /*







|







4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
    const char **argv)		/* Argument strings. */
{
    char *buf, *oldData;
    Tcl_InterpDeleteProc *procPtr;

    if (argc != 3) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" data_key data_item\"", (char *)NULL);
	return TCL_ERROR;
    }

    buf = (char *)Tcl_Alloc(strlen(argv[2]) + 1);
    strcpy(buf, argv[2]);

    /*
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
    size_t length;
    TclPlatformType *platform;

    platform = TclGetPlatform();

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" platform\"", NULL);
	return TCL_ERROR;
    }

    length = strlen(argv[1]);
    if (strncmp(argv[1], "unix", length) == 0) {
	*platform = TCL_PLATFORM_UNIX;
    } else if (strncmp(argv[1], "windows", length) == 0) {
	*platform = TCL_PLATFORM_WINDOWS;
    } else {
	Tcl_AppendResult(interp, "unsupported platform: should be one of "
		"unix, or windows", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TeststaticpkgCmd --
 *
 *	This procedure implements the "teststaticpkg" command.
 *	It is used to test the procedure Tcl_StaticPackage.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	When the packge given by argv[1] is loaded into an interpeter,
 *	variable "x" in that interpreter is set to "loaded".
 *
 *----------------------------------------------------------------------
 */

static int
TeststaticpkgCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int safe, loaded;

    if (argc != 4) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"",
		argv[0], " pkgName safe loaded\"", NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetInt(interp, argv[2], &safe) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_GetInt(interp, argv[3], &loaded) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage((loaded) ? interp : NULL, argv[1],
	    StaticInitProc, (safe) ? StaticInitProc : NULL);
    return TCL_OK;
}

static int
StaticInitProc(
    Tcl_Interp *interp)		/* Interpreter in which package is supposedly







|










|








|

|
|





|






|









|








|







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
    size_t length;
    TclPlatformType *platform;

    platform = TclGetPlatform();

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"", argv[0],
		" platform\"", (char *)NULL);
	return TCL_ERROR;
    }

    length = strlen(argv[1]);
    if (strncmp(argv[1], "unix", length) == 0) {
	*platform = TCL_PLATFORM_UNIX;
    } else if (strncmp(argv[1], "windows", length) == 0) {
	*platform = TCL_PLATFORM_WINDOWS;
    } else {
	Tcl_AppendResult(interp, "unsupported platform: should be one of "
		"unix, or windows", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TeststaticlibraryCmd --
 *
 *	This procedure implements the "teststaticlibrary" command.
 *	It is used to test the procedure Tcl_StaticLibrary.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	When the package given by argv[1] is loaded into an interpreter,
 *	variable "x" in that interpreter is set to "loaded".
 *
 *----------------------------------------------------------------------
 */

static int
TeststaticlibraryCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int safe, loaded;

    if (argc != 4) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"",
		argv[0], " prefix safe loaded\"", (char *)NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetInt(interp, argv[2], &safe) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_GetInt(interp, argv[3], &loaded) != TCL_OK) {
	return TCL_ERROR;
    }
    Tcl_StaticLibrary((loaded) ? interp : NULL, argv[1],
	    StaticInitProc, (safe) ? StaticInitProc : NULL);
    return TCL_OK;
}

static int
StaticInitProc(
    Tcl_Interp *interp)		/* Interpreter in which package is supposedly
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
    const char **argv)		/* Argument strings. */
{
    Tcl_DString buffer;
    const char *result;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"",
		argv[0], " path\"", NULL);
	return TCL_ERROR;
    }
    result = Tcl_TranslateFileName(interp, argv[1], &buffer);
    if (result == NULL) {
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, result, NULL);
    Tcl_DStringFree(&buffer);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|






|







4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
    const char **argv)		/* Argument strings. */
{
    Tcl_DString buffer;
    const char *result;

    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"",
		argv[0], " path\"", (char *)NULL);
	return TCL_ERROR;
    }
    result = Tcl_TranslateFileName(interp, argv[1], &buffer);
    if (result == NULL) {
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, result, (char *)NULL);
    Tcl_DStringFree(&buffer);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int flags = 0;

    if ((argc != 5) && (argc != 6)) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"",
		argv[0], " level name ?name2? dest global\"", NULL);
	return TCL_ERROR;
    }

    if (argc == 5) {
	if (strcmp(argv[4], "global") == 0) {
	    flags = TCL_GLOBAL_ONLY;
	} else if (strcmp(argv[4], "namespace") == 0) {







|







5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int flags = 0;

    if ((argc != 5) && (argc != 6)) {
	Tcl_AppendResult(interp, "wrong # arguments: should be \"",
		argv[0], " level name ?name2? dest global\"", (char *)NULL);
	return TCL_ERROR;
    }

    if (argc == 5) {
	if (strcmp(argv[4], "global") == 0) {
	    flags = TCL_GLOBAL_ONLY;
	} else if (strcmp(argv[4], "namespace") == 0) {
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
TestseterrorcodeCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc > 6) {
	Tcl_AppendResult(interp, "too many args", NULL);
	return TCL_ERROR;
    }
    switch (argc) {
    case 1:
	Tcl_SetErrorCode(interp, "NONE", NULL);
	break;
    case 2:
	Tcl_SetErrorCode(interp, argv[1], NULL);
	break;
    case 3:
	Tcl_SetErrorCode(interp, argv[1], argv[2], NULL);
	break;
    case 4:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], NULL);
	break;
    case 5:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], NULL);
	break;
    case 6:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4],
		argv[5], NULL);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *







|




|


|


|


|


|



|







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
TestseterrorcodeCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    if (argc > 6) {
	Tcl_AppendResult(interp, "too many args", (char *)NULL);
	return TCL_ERROR;
    }
    switch (argc) {
    case 1:
	Tcl_SetErrorCode(interp, "NONE", (char *)NULL);
	break;
    case 2:
	Tcl_SetErrorCode(interp, argv[1], (char *)NULL);
	break;
    case 3:
	Tcl_SetErrorCode(interp, argv[1], argv[2], (char *)NULL);
	break;
    case 4:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], (char *)NULL);
	break;
    case 5:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4], (char *)NULL);
	break;
    case 6:
	Tcl_SetErrorCode(interp, argv[1], argv[2], argv[3], argv[4],
		argv[5], (char *)NULL);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
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
{
    static Tcl_Interp *interp2 = NULL;
    int code;
    Tcl_Channel chan;

    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option ?arg ...?", NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "cmd") == 0) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " cmd script", NULL);
	    return TCL_ERROR;
	}
	if (interp2 != NULL) {
	    code = Tcl_EvalEx(interp2, argv[2], -1, TCL_EVAL_GLOBAL);
	    Tcl_SetObjResult(interp, Tcl_GetObjResult(interp2));
	    return code;
	} else {
	    Tcl_AppendResult(interp,
		    "called \"testfevent code\" before \"testfevent create\"",
		    NULL);
	    return TCL_ERROR;
	}
    } else if (strcmp(argv[1], "create") == 0) {
	if (interp2 != NULL) {
	    Tcl_DeleteInterp(interp2);
	}
	interp2 = Tcl_CreateInterp();







|





|



|





|







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
{
    static Tcl_Interp *interp2 = NULL;
    int code;
    Tcl_Channel chan;

    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" option ?arg ...?", (char *)NULL);
	return TCL_ERROR;
    }
    if (strcmp(argv[1], "cmd") == 0) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " cmd script", (char *)NULL);
	    return TCL_ERROR;
	}
	if (interp2 != NULL) {
	    code = Tcl_EvalEx(interp2, argv[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\"",
		    (char *)NULL);
	    return TCL_ERROR;
	}
    } else if (strcmp(argv[1], "create") == 0) {
	if (interp2 != NULL) {
	    Tcl_DeleteInterp(interp2);
	}
	interp2 = Tcl_CreateInterp();
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
	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_DecrRefCount(error);
	}
	Tcl_AppendResult(interp, Tcl_ErrnoId(), NULL);
    }

  end:
    return result;
}

/*







|



|







5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
	result = TCL_ERROR;
	goto end;
    }

    if (result != TCL_OK) {
	if (error != NULL) {
	    if (Tcl_GetString(error)[0] != '\0') {
		Tcl_AppendResult(interp, Tcl_GetString(error), " ", (char *)NULL);
	    }
	    Tcl_DecrRefCount(error);
	}
	Tcl_AppendResult(interp, Tcl_ErrnoId(), (char *)NULL);
    }

  end:
    return result;
}

/*
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
/*
 *----------------------------------------------------------------------
 *
 * GetTimesObjCmd --
 *
 *	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.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Allocates and frees memory, sets a variable "a" in the interpreter.
 *







|







5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
/*
 *----------------------------------------------------------------------
 *
 * GetTimesObjCmd --
 *
 *	This procedure implements the "gettimes" command.  It is used for
 *	computing the time needed for various basic operations such as reading
 *	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.
 *
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
    }
    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");
    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",
	    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) {







|







|







5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
    }
    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, "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 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
	}
    }
    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");
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	sprintf(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",
	    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");







|
|


|



|







5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
	}
    }
    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);

    /* snprintf 100000 times */
    fprintf(stderr, "snprintf of 12345 100000 times\n");
    Tcl_GetTime(&start);
    for (i = 0;  i < 100000;  i++) {
	snprintf(newString, sizeof(newString), "%d", 12345);
    }
    Tcl_GetTime(&stop);
    timePer = (stop.sec - start.sec)*1000000 + (stop.usec - start.usec);
    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");
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
static int
TeststringbytesObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    int 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);







|







5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
static int
TeststringbytesObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{
    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);
5034
5035
5036
5037
5038
5039
5040

5041
5042
5043
5044
5045
5046






5047
5048
5049
5050
5051
5052
5053
    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;
    }

    if (Tcl_IsShared(objv[1])) {
	obj = Tcl_DuplicateObj(objv[1]);
    } else {
	obj = objv[1];
    }
    Tcl_SetByteArrayLength(obj, n);






    Tcl_SetObjResult(interp, obj);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







>
|
|
<
<

|
>
>
>
>
>
>







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
    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(obj)) {
	obj = Tcl_DuplicateObj(obj);


    }
    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;
}

/*
 *----------------------------------------------------------------------
 *
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
TestbytestringObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* The argument objects. */
{




    size_t n = 0;



    const char *p;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "bytearray");
	return TCL_ERROR;
    }

    p = (const char *)TclGetBytesFromObj(interp, objv[1], &n);
    if (p == NULL) {
	return TCL_ERROR;
    }





    Tcl_SetObjResult(interp, Tcl_NewStringObj(p, n));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsetCmd --







>
>
>
>
|
>
>
>







|



>
>
>
>
>
|







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
static int
TestbytestringObjCmd(
    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
	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 *)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, x.n));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestsetCmd --
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
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    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 (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);
	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);
	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 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 (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);
	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");
	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  --
 *







|







|








|














|







|








|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int flags = PTR2INT(data);
    const char *value;

    if (argc == 2) {
	Tcl_AppendResult(interp, "before get", (char *)NULL);
	value = Tcl_GetVar2(interp, argv[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", (char *)NULL);
	value = Tcl_SetVar2(interp, argv[1], NULL, argv[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?\"", (char *)NULL);
	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 flags = PTR2INT(data);
    const char *value;

    if (argc == 3) {
	Tcl_AppendResult(interp, "before get", (char *)NULL);
	value = Tcl_GetVar2(interp, argv[1], argv[2], flags);
	if (value == NULL) {
	    return TCL_ERROR;
	}
	Tcl_AppendElement(interp, value);
	return TCL_OK;
    } else if (argc == 4) {
	Tcl_AppendResult(interp, "before set", (char *)NULL);
	value = Tcl_SetVar2(interp, argv[1], argv[2], argv[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?\"", (char *)NULL);
	return TCL_ERROR;
    }































































































































}

/*
 *----------------------------------------------------------------------
 *
 * TestmainthreadCmd  --
 *
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
{
    if (argc == 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);
	return TCL_ERROR;
    }
}

/*
 *----------------------------------------------------------------------
 *







|







5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
{
    if (argc == 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", (char *)NULL);
	return TCL_ERROR;
    }
}

/*
 *----------------------------------------------------------------------
 *
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
    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. */
    int IOQueued;		/* How much IO is queued inside channel? */
    char buf[TCL_INTEGER_SPACE];/* For sprintf. */
    int mode;			/* rw mode of the channel */

    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" subcommand ?additional args..?\"", NULL);
	return TCL_ERROR;
    }
    cmdName = argv[1];
    len = strlen(cmdName);

    chanPtr = NULL;








|




|







6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
    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. */
    int IOQueued;		/* How much IO is queued inside channel? */
    char buf[TCL_INTEGER_SPACE];/* For snprintf. */
    int mode;			/* rw mode of the channel */

    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" subcommand ?additional args..?\"", (char *)NULL);
	return TCL_ERROR;
    }
    cmdName = argv[1];
    len = strlen(cmdName);

    chanPtr = NULL;

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
    } else {
	statePtr	= NULL;
	chan		= NULL;
    }

    if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerror", len) == 0)) {

	Tcl_Obj *msg = Tcl_NewStringObj(argv[3],-1);

	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_IncrRefCount(msg);
	Tcl_SetChannelErrorInterp(interp, msg);
	Tcl_DecrRefCount(msg);

	Tcl_GetChannelErrorInterp(interp, &msg);
	Tcl_SetObjResult(interp, msg);







|












|







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
    } else {
	statePtr	= NULL;
	chan		= NULL;
    }

    if ((cmdName[0] == 's') && (strncmp(cmdName, "setchannelerror", len) == 0)) {

	Tcl_Obj *msg = Tcl_NewStringObj(argv[3], -1);

	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_IncrRefCount(msg);
	Tcl_SetChannelErrorInterp(interp, msg);
	Tcl_DecrRefCount(msg);

	Tcl_GetChannelErrorInterp(interp, &msg);
	Tcl_SetObjResult(interp, msg);
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
     */

    if ((cmdName[0] == 'c') && (strncmp(cmdName, "cut", len) == 0)) {
	TestChannel *det;

	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " cut channelName\"", NULL);
	    return TCL_ERROR;
	}

	Tcl_RegisterChannel(NULL, chan); /* prevent closing */
	Tcl_UnregisterChannel(interp, chan);

	Tcl_CutChannel(chan);







|







6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
     */

    if ((cmdName[0] == 'c') && (strncmp(cmdName, "cut", len) == 0)) {
	TestChannel *det;

	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " cut channelName\"", (char *)NULL);
	    return TCL_ERROR;
	}

	Tcl_RegisterChannel(NULL, chan); /* prevent closing */
	Tcl_UnregisterChannel(interp, chan);

	Tcl_CutChannel(chan);
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
	return TCL_OK;
    }

    if ((cmdName[0] == 'c') &&
	    (strncmp(cmdName, "clearchannelhandlers", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " 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],
		    " info channelName\"", NULL);
	    return TCL_ERROR;
	}
	Tcl_AppendElement(interp, argv[2]);
	Tcl_AppendElement(interp, Tcl_ChannelName(chanPtr->typePtr));
	if (statePtr->flags & TCL_READABLE) {
	    Tcl_AppendElement(interp, "read");
	} else {







|









|







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
	return TCL_OK;
    }

    if ((cmdName[0] == 'c') &&
	    (strncmp(cmdName, "clearchannelhandlers", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " clearchannelhandlers channelName\"", (char *)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],
		    " info channelName\"", (char *)NULL);
	    return TCL_ERROR;
	}
	Tcl_AppendElement(interp, argv[2]);
	Tcl_AppendElement(interp, Tcl_ChannelName(chanPtr->typePtr));
	if (statePtr->flags & TCL_READABLE) {
	    Tcl_AppendElement(interp, "read");
	} else {
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

	return TCL_OK;
    }

    if ((cmdName[0] == 'i') &&
	    (strncmp(cmdName, "inputbuffered", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}
	IOQueued = Tcl_InputBuffered(chan);
	TclFormatInt(buf, IOQueued);
	Tcl_AppendResult(interp, buf, NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'i') && (strncmp(cmdName, "isshared", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}

	TclFormatInt(buf, Tcl_IsChannelShared(chan));
	Tcl_AppendResult(interp, buf, NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'i') && (strncmp(cmdName, "isstandard", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}

	TclFormatInt(buf, Tcl_IsStandardChannel(chan));
	Tcl_AppendResult(interp, buf, NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'm') && (strncmp(cmdName, "mode", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", 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, "mthread", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}

	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		(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);
	    return TCL_ERROR;
	}
	Tcl_AppendResult(interp, statePtr->channelName, 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);
	    return TCL_ERROR;
	}

	IOQueued = Tcl_OutputBuffered(chan);
	TclFormatInt(buf, IOQueued);
	Tcl_AppendResult(interp, buf, NULL);
	return TCL_OK;
    }

    if ((cmdName[0] == 'q') &&
	    (strncmp(cmdName, "queuedcr", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}

	Tcl_AppendResult(interp,
		(statePtr->flags & INPUT_SAW_CR) ? "1" : "0", 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;







|




|





|




|





|




|





|
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|










|


|



















|





|






|




|







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

	return TCL_OK;
    }

    if ((cmdName[0] == 'i') &&
	    (strncmp(cmdName, "inputbuffered", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}
	IOQueued = Tcl_InputBuffered(chan);
	TclFormatInt(buf, IOQueued);
	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", (char *)NULL);
	    return TCL_ERROR;
	}

	TclFormatInt(buf, Tcl_IsChannelShared(chan));
	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", (char *)NULL);
	    return TCL_ERROR;
	}

	TclFormatInt(buf, Tcl_IsStandardChannel(chan));
	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", (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 (argc != 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 (argc != 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 (argc != 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", (char *)NULL);
	    return TCL_ERROR;
	}

	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		(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", (char *)NULL);
	    return TCL_ERROR;
	}
	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", (char *)NULL);
	    return TCL_ERROR;
	}

	IOQueued = Tcl_OutputBuffered(chan);
	TclFormatInt(buf, IOQueued);
	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", (char *)NULL);
	    return TCL_ERROR;
	}

	Tcl_AppendResult(interp,
		(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;
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
	    }
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", NULL);
	    return TCL_ERROR;
	}

	TclFormatInt(buf, statePtr->refCount);
	Tcl_AppendResult(interp, buf, 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);
	    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);
	    return TCL_ERROR;
	}
	Tcl_AppendResult(interp, Tcl_ChannelName(chanPtr->typePtr), 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;







|




|












|













|


|







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
	    }
	}
	return TCL_OK;
    }

    if ((cmdName[0] == 'r') && (strncmp(cmdName, "refcount", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "channel name required", (char *)NULL);
	    return TCL_ERROR;
	}

	TclFormatInt(buf, statePtr->refCount);
	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", (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", (char *)NULL);
	    return TCL_ERROR;
	}
	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;
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
    if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
	/*
	 * Syntax: transform channel -command command
	 */

	if (argc != 5) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " transform channelId -command cmd\"", NULL);
	    return TCL_ERROR;
	}
	if (strcmp(argv[3], "-command") != 0) {
	    Tcl_AppendResult(interp, "bad argument \"", argv[3],
		    "\": should be \"-command\"", NULL);
	    return TCL_ERROR;
	}

	return TclChannelTransform(interp, chan,
		Tcl_NewStringObj(argv[4], -1));
    }

    if ((cmdName[0] == 'u') && (strncmp(cmdName, "unstack", len) == 0)) {
	/*
	 * Syntax: unstack channel
	 */

	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " unstack channel\"", NULL);
	    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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestChannelEventCmd --







|




|














|







|







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
    if ((cmdName[0] == 't') && (strncmp(cmdName, "transform", len) == 0)) {
	/*
	 * Syntax: transform channel -command command
	 */

	if (argc != 5) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " transform channelId -command cmd\"", (char *)NULL);
	    return TCL_ERROR;
	}
	if (strcmp(argv[3], "-command") != 0) {
	    Tcl_AppendResult(interp, "bad argument \"", argv[3],
		    "\": should be \"-command\"", (char *)NULL);
	    return TCL_ERROR;
	}

	return TclChannelTransform(interp, chan,
		Tcl_NewStringObj(argv[4], -1));
    }

    if ((cmdName[0] == 'u') && (strncmp(cmdName, "unstack", len) == 0)) {
	/*
	 * Syntax: unstack channel
	 */

	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " unstack channel\"", (char *)NULL);
	    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", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestChannelEventCmd --
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
    ChannelState *statePtr;	/* state info for channel */
    EventScriptRecord *esPtr, *prevEsPtr, *nextEsPtr;
    const char *cmd;
    int index, i, mask, len;

    if ((argc < 3) || (argc > 5)) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" channelName cmd ?arg1? ?arg2?\"", NULL);
	return TCL_ERROR;
    }
    chanPtr = (Channel *) Tcl_GetChannel(interp, argv[1], NULL);
    if (chanPtr == NULL) {
	return TCL_ERROR;
    }
    statePtr = chanPtr->state;

    cmd = argv[2];
    len = strlen(cmd);
    if ((cmd[0] == 'a') && (strncmp(cmd, "add", len) == 0)) {
	if (argc != 5) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName add eventSpec script\"", NULL);
	    return TCL_ERROR;
	}
	if (strcmp(argv[3], "readable") == 0) {
	    mask = TCL_READABLE;
	} else if (strcmp(argv[3], "writable") == 0) {
	    mask = TCL_WRITABLE;
	} else if (strcmp(argv[3], "none") == 0) {
	    mask = 0;
	} else {
	    Tcl_AppendResult(interp, "bad event name \"", argv[3],
		    "\": must be readable, writable, or none", NULL);
	    return TCL_ERROR;
	}

	esPtr = (EventScriptRecord *)Tcl_Alloc(sizeof(EventScriptRecord));
	esPtr->nextPtr = statePtr->scriptRecordPtr;
	statePtr->scriptRecordPtr = esPtr;








|













|










|







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
    ChannelState *statePtr;	/* state info for channel */
    EventScriptRecord *esPtr, *prevEsPtr, *nextEsPtr;
    const char *cmd;
    int index, i, mask, len;

    if ((argc < 3) || (argc > 5)) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" channelName cmd ?arg1? ?arg2?\"", (char *)NULL);
	return TCL_ERROR;
    }
    chanPtr = (Channel *) Tcl_GetChannel(interp, argv[1], NULL);
    if (chanPtr == NULL) {
	return TCL_ERROR;
    }
    statePtr = chanPtr->state;

    cmd = argv[2];
    len = strlen(cmd);
    if ((cmd[0] == 'a') && (strncmp(cmd, "add", len) == 0)) {
	if (argc != 5) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName add eventSpec script\"", (char *)NULL);
	    return TCL_ERROR;
	}
	if (strcmp(argv[3], "readable") == 0) {
	    mask = TCL_READABLE;
	} else if (strcmp(argv[3], "writable") == 0) {
	    mask = TCL_WRITABLE;
	} else if (strcmp(argv[3], "none") == 0) {
	    mask = 0;
	} else {
	    Tcl_AppendResult(interp, "bad event name \"", argv[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;

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

	return TCL_OK;
    }

    if ((cmd[0] == 'd') && (strncmp(cmd, "delete", len) == 0)) {
	if (argc != 4) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName delete index\"", NULL);
	    return TCL_ERROR;
	}
	if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if (index < 0) {
	    Tcl_AppendResult(interp, "bad event index: ", argv[3],
		    ": must be nonnegative", 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);
	    return TCL_ERROR;
	}
	if (esPtr == statePtr->scriptRecordPtr) {
	    statePtr->scriptRecordPtr = esPtr->nextPtr;
	} else {
	    for (prevEsPtr = statePtr->scriptRecordPtr;
		 (prevEsPtr != NULL) &&







|







|









|







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

	return TCL_OK;
    }

    if ((cmd[0] == 'd') && (strncmp(cmd, "delete", len) == 0)) {
	if (argc != 4) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName delete index\"", (char *)NULL);
	    return TCL_ERROR;
	}
	if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if (index < 0) {
	    Tcl_AppendResult(interp, "bad event index: ", argv[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", (char *)NULL);
	    return TCL_ERROR;
	}
	if (esPtr == statePtr->scriptRecordPtr) {
	    statePtr->scriptRecordPtr = esPtr->nextPtr;
	} else {
	    for (prevEsPtr = statePtr->scriptRecordPtr;
		 (prevEsPtr != NULL) &&
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019

	return TCL_OK;
    }

    if ((cmd[0] == 'l') && (strncmp(cmd, "list", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName list\"", NULL);
	    return TCL_ERROR;
	}
	resultListPtr = Tcl_GetObjResult(interp);
	for (esPtr = statePtr->scriptRecordPtr;
	     esPtr != NULL;
	     esPtr = esPtr->nextPtr) {
	    if (esPtr->mask) {







|







6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616

	return TCL_OK;
    }

    if ((cmd[0] == 'l') && (strncmp(cmd, "list", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName list\"", (char *)NULL);
	    return TCL_ERROR;
	}
	resultListPtr = Tcl_GetObjResult(interp);
	for (esPtr = statePtr->scriptRecordPtr;
	     esPtr != NULL;
	     esPtr = esPtr->nextPtr) {
	    if (esPtr->mask) {
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
	Tcl_SetObjResult(interp, resultListPtr);
	return TCL_OK;
    }

    if ((cmd[0] == 'r') && (strncmp(cmd, "removeall", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName removeall\"", NULL);
	    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) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName delete index event\"", NULL);
	    return TCL_ERROR;
	}
	if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if (index < 0) {
	    Tcl_AppendResult(interp, "bad event index: ", argv[3],
		    ": must be nonnegative", 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);
	    return TCL_ERROR;
	}

	if (strcmp(argv[4], "readable") == 0) {
	    mask = TCL_READABLE;
	} else if (strcmp(argv[4], "writable") == 0) {
	    mask = TCL_WRITABLE;
	} else if (strcmp(argv[4], "none") == 0) {
	    mask = 0;
	} else {
	    Tcl_AppendResult(interp, "bad event name \"", argv[4],
		    "\": must be readable, writable, or none", 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);
    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.
 *
 *----------------------------------------------------------------------
 */





static int
TestSocketCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Interpreter for result. */
    int argc,			/* Count of additional args. */
    const char **argv)		/* Additional arg strings. */
{
    const char *cmdName;	/* Sub command. */
    size_t len;			/* Length of subcommand string. */

    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" subcommand ?additional args..?\"", NULL);
	return TCL_ERROR;
    }
    cmdName = argv[1];
    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_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_AppendResult(interp, "bad option \"", cmdName, "\": should be "
	    "testflags", NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestServiceModeCmd --







|


















|







|









|











|








|




















>
>
>
>












|






|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
>
>
>
|



|







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
	Tcl_SetObjResult(interp, resultListPtr);
	return TCL_OK;
    }

    if ((cmd[0] == 'r') && (strncmp(cmd, "removeall", len) == 0)) {
	if (argc != 3) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName removeall\"", (char *)NULL);
	    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) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " channelName delete index event\"", (char *)NULL);
	    return TCL_ERROR;
	}
	if (Tcl_GetInt(interp, argv[3], &index) == TCL_ERROR) {
	    return TCL_ERROR;
	}
	if (index < 0) {
	    Tcl_AppendResult(interp, "bad event index: ", argv[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", (char *)NULL);
	    return TCL_ERROR;
	}

	if (strcmp(argv[4], "readable") == 0) {
	    mask = TCL_READABLE;
	} else if (strcmp(argv[4], "writable") == 0) {
	    mask = TCL_WRITABLE;
	} else if (strcmp(argv[4], "none") == 0) {
	    mask = 0;
	} else {
	    Tcl_AppendResult(interp, "bad event name \"", argv[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", (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. */
{
    const char *cmdName;	/* Sub command. */
    size_t len;			/* Length of subcommand string. */

    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" subcommand ?additional args..?\"", (char *)NULL);
	return TCL_ERROR;
    }
    cmdName = argv[1];
    len = strlen(cmdName);

    if ((cmdName[0] == 't') && (strncmp(cmdName, "testflags", len) == 0)) {
	Tcl_Channel hChannel;
	int modePtr;
	int testMode;
	TcpState *statePtr;
	/* Set test value in the socket driver
	 */
	/* Check for argument "channel name"
	 */
	if (argc < 4) {
	    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		    " testflags channel flags\"", (char *)NULL);
	    return TCL_ERROR;
	}
	hChannel = Tcl_GetChannel(interp, argv[2], &modePtr);
	if ( NULL == hChannel ) {
	    Tcl_AppendResult(interp, "unknown channel:", argv[2], (char *)NULL);
	    return TCL_ERROR;
	}
	statePtr = (TcpState *)Tcl_GetChannelInstanceData(hChannel);
	if ( NULL == statePtr) {
	    Tcl_AppendResult(interp, "No channel instance data:", argv[2],
		    (char *)NULL);
	    return TCL_ERROR;
	}
	if (Tcl_GetBoolean(interp, argv[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", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TestServiceModeCmd --
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
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int newmode, oldmode;
    if (argc > 2) {
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
                         " ?newmode?\"", NULL);
        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);
        }
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(oldmode));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestWrongNumArgsObjCmd --







|
|
|



|
|
|
|
|
|
|
|

|







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
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int argc,			/* Number of arguments. */
    const char **argv)		/* Argument strings. */
{
    int newmode, oldmode;
    if (argc > 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
			 " ?newmode?\"", (char *)NULL);
	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);
	}
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(oldmode));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestWrongNumArgsObjCmd --
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
 *----------------------------------------------------------------------
 */

static int
TestWrongNumArgsObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int i, length;
    const char *msg;

    if (objc < 3) {
	/*
	 * Don't use Tcl_WrongNumArgs here, as that is the function
	 * we want to test!
	 */
	Tcl_AppendResult(interp, "insufficient arguments", NULL);
	return TCL_ERROR;
    }

    if (Tcl_GetIntFromObj(interp, objv[1], &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.
	 */

	Tcl_AppendResult(interp, "insufficient arguments", NULL);
	return TCL_ERROR;
    }

    Tcl_WrongNumArgs(interp, i, &(objv[3]), msg);
    return TCL_OK;
}








|


|



<
<
|
<
<
<


|












>
|







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
 *----------------------------------------------------------------------
 */

static int
TestWrongNumArgsObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Size i, length;
    const char *msg;

    if (objc < 3) {


	goto insufArgs;



    }

    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", (char *)NULL);
	return TCL_ERROR;
    }

    Tcl_WrongNumArgs(interp, i, &(objv[3]), msg);
    return TCL_OK;
}

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
TestGetIndexFromObjStructObjCmd(
    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
    };
    int idx,target;


    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "argument targetvalue");
	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 (idx != target) {
	char buffer[64];
	sprintf(buffer, "%d", idx);
	Tcl_AppendResult(interp, "index value comparison failed: got ",
		buffer, NULL);
	sprintf(buffer, "%d", target);
	Tcl_AppendResult(interp, " when ", buffer, " expected", NULL);
	return TCL_ERROR;
    }
    Tcl_WrongNumArgs(interp, 3, objv, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestFilesystemObjCmd --







|

|
>

|
|
<
<
<
<





>
>
>
>
>
>
>
>
>
>
>
|

|

|
|
|


|







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
TestGetIndexFromObjStructObjCmd(
    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", "ee", "ff", NULL, NULL
    };
    int target, flags = 0;
    signed char idx[8];

    if (objc != 3 && objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "argument targetvalue ?flags?");




	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;
    } else if (idx[1] != target) {
	char buffer[64];
	snprintf(buffer, sizeof(buffer), "%d", idx[1]);
	Tcl_AppendResult(interp, "index value comparison failed: got ",
		buffer, (char *)NULL);
	snprintf(buffer, sizeof(buffer), "%d", target);
	Tcl_AppendResult(interp, " when ", buffer, " expected", (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_WrongNumArgs(interp, objc, objv, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestFilesystemObjCmd --
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
	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_DStringFree(&ds);
	Tcl_ResetResult(interp);
	Tcl_SetObjResult(interp, savedResult);
	Tcl_DecrRefCount(savedResult);
    }
}








|







7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
	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), TCL_INDEX_NONE, 0);
	Tcl_DStringFree(&ds);
	Tcl_ResetResult(interp);
	Tcl_SetObjResult(interp, savedResult);
	Tcl_DecrRefCount(savedResult);
    }
}

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
 * (native) directory.
 */

static Tcl_Obj *
SimpleRedirect(
    Tcl_Obj *pathPtr)		/* Name of file to copy. */
{
    int 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);
    Tcl_IncrRefCount(origPtr);
    return origPtr;
}

static int
SimpleMatchInDirectory(
    Tcl_Interp *interp,		/* Interpreter for error







|













|







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
 * (native) directory.
 */

static Tcl_Obj *
SimpleRedirect(
    Tcl_Obj *pathPtr)		/* Name of file to copy. */
{
    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);
    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
     * 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_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);







|







7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
     * 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) {
	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
    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);
	return NULL;
    }

    tempPtr = SimpleRedirect(pathPtr);
    chan = Tcl_FSOpenFileChannel(interp, tempPtr, "r", permissions);
    Tcl_DecrRefCount(tempPtr);
    return chan;







|
|







7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
    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 & 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
static int
TestUtfNextCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    size_t 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]);
	numBytes = objv[1]->length;

    if (numBytes > (int)sizeof(buffer) - 4) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"testutfnext\" can only handle %d bytes",
		(int)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);
	    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) {


	    first = buffer;
	    break;
	}
    }

    Tcl_SetObjResult(interp, Tcl_NewIntObj(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;
    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]);
    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);
    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]);
	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_UtfFindFirst
 */








|










|
<

|

|
|











|








>
>
|
|



|
















|








|
<














|
















|
|
<












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
static int
TestUtfNextCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    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_GetStringFromObj(objv[1], &numBytes);


    if ((size_t)numBytes > sizeof(buffer) - 4) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"\"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]", (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"
		    "Different result when src[end] is %#x", UCHAR(p[-1])));
	    return TCL_ERROR;
	}
    }

    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[])
{
    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_GetStringFromObj(objv[1], &numBytes);


    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 = 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) {
	Tcl_Size numBytes, len, limit = TCL_INDEX_NONE;
	const char *bytes = Tcl_GetStringFromObj(objv[1], &numBytes);


	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
	    (void) Tcl_GetIntFromObj(interp, objv[2], &len);
	}
	Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_UtfFindLast(Tcl_GetString(objv[1]), len), -1));
    }
    return TCL_OK;
}




























#if defined(HAVE_CPUID) || defined(_WIN32)
/*
 *----------------------------------------------------------------------
 *
 * TestcpuidCmd --
 *
 *	Retrieves CPU ID information.
 *







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







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
	    (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(MAC_OSX_TCL)
/*
 *----------------------------------------------------------------------
 *
 * TestcpuidCmd --
 *
 *	Retrieves CPU ID information.
 *
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
    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]);
    }
    Tcl_SetObjResult(interp, Tcl_NewListObj(4, regsObjs));
    return TCL_OK;
}
#endif

/*







|







7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
    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_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
    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_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_DeleteHashTable(&hash);
	    return TCL_ERROR;
	}
	Tcl_SetHashValue(hPtr, INT2PTR(i+42));
    }

    if (hash.numEntries != (size_t)limit) {
	Tcl_AppendResult(interp, "unexpected maximal size", NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }

    for (i=0 ; i<limit ; 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_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_DeleteHashTable(&hash);
	    return TCL_ERROR;
	}
	Tcl_DeleteHashEntry(hPtr);
    }

    if (hash.numEntries != 0) {
	Tcl_AppendResult(interp, "non-zero final size", NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }

    Tcl_DeleteHashTable(&hash);
    Tcl_AppendResult(interp, "OK", 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)
{
    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args", NULL);
	return TCL_ERROR;
    } else {
	int val, i, total=0;

	for (i=1 ; i<argc ; i++) {
	    if (Tcl_GetInt(interp, argv[i], &val) != TCL_OK) {
		return TCL_ERROR;
	    }
	    total += val;
	}
	Tcl_SetObjResult(interp, Tcl_NewIntObj(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*/)
{
    if (argc != 1) {
	Tcl_AppendResult(interp, "wrong # args", NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(sizeof(long)));
    return TCL_OK;
}

static int
NREUnwind_callback(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    int none;

    if (data[0] == INT2PTR(-1)) {
        Tcl_NRAddCallback(interp, NREUnwind_callback, &none, INT2PTR(-1),
                INT2PTR(-1), NULL);
    } else if (data[1] == INT2PTR(-1)) {
        Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], &none,
                INT2PTR(-1), NULL);
    } else if (data[2] == INT2PTR(-1)) {
        Tcl_NRAddCallback(interp, NREUnwind_callback, data[0], data[1],
                &none, 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));
    }
    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);
    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;
    Tcl_Obj *levels[6];
    int i = 0;
    NRE_callback *cbPtr = iPtr->execEnvPtr->callbackPtr;

    if (refDepth == NULL) {
	refDepth = &depth;
    }

    depth = (refDepth - &depth);

    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
	    - iPtr->execEnvPtr->execStackPtr->stackWords);

    while (cbPtr) {
	i++;
	cbPtr = cbPtr->nextPtr;
    }
    levels[5] = Tcl_NewIntObj(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
 *	[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_Obj *list1Ptr, *list2Ptr, *emptyPtr, *concatPtr, *tmpPtr;
    int result = TCL_OK, 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.
     */








|







|
|






|
|







|
|




|
|







|





|















|










|















|


|









|


|
|

|
|

|
|

|
|
|
|
|

















|












|
|

|



|


|

|
|
|
|
|






|












|



















|
>







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
    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", (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_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 != (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));
	if (hPtr == NULL) {
	    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_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", (char *)NULL);
	Tcl_DeleteHashTable(&hash);
	return TCL_ERROR;
    }

    Tcl_DeleteHashTable(&hash);
    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)
{
    if (argc < 2) {
	Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
	return TCL_ERROR;
    } else {
	int val, i, total=0;

	for (i=1 ; i<argc ; i++) {
	    if (Tcl_GetInt(interp, argv[i], &val) != TCL_OK) {
		return TCL_ERROR;
	    }
	    total += val;
	}
	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*/)
{
    if (argc != 1) {
	Tcl_AppendResult(interp, "wrong # args", (char *)NULL);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sizeof(long)));
    return TCL_OK;
}

static int
NREUnwind_callback(
    void *data[],
    Tcl_Interp *interp,
    TCL_UNUSED(int) /*result*/)
{
    void *cStackPtr = TclGetCStackPtr();

    if (data[0] == INT2PTR(-1)) {
	Tcl_NRAddCallback(interp, NREUnwind_callback, cStackPtr, INT2PTR(-1),
		INT2PTR(-1), NULL);
    } else if (data[1] == INT2PTR(-1)) {
	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],
		cStackPtr, NULL);
    } else {
	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);
    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 Tcl_Size *refDepth = NULL;
    Tcl_Size depth;
    Tcl_Obj *levels[6];
    Tcl_Size i = 0;
    NRE_callback *cbPtr = iPtr->execEnvPtr->callbackPtr;

    if (refDepth == NULL) {
	refDepth = (ptrdiff_t *)TclGetCStackPtr();
    }

    depth = (refDepth - (ptrdiff_t *)TclGetCStackPtr());

    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_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 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_Obj *list1Ptr, *list2Ptr, *emptyPtr, *concatPtr, *tmpPtr;
    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

    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);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (a) concatObj is not a new obj ",
		NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(no new refCount)", NULL);
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(refCount added)", NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(more than one refCount added!)", 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);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (b) concatObj is not a new obj ",
		NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(refCount removed?)", NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(no new refCount)", NULL);
	    break;
	case 2:
	    Tcl_AppendResult(interp, "(refCount added)", NULL);
	    Tcl_DecrRefCount(tmpPtr);
	    break;
	default:
	    Tcl_AppendResult(interp, "(more than one refCount added!)", 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);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (c) concatObj is not a new obj ",
		NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(no new refCount)", NULL);
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(refCount added)", NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(more than one refCount added!)", 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);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (d) concatObj is not a new obj ",
		NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(refCount removed?)", NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(no new refCount)", NULL);
	    break;
	case 2:
	    Tcl_AppendResult(interp, "(refCount added)", NULL);
	    Tcl_DecrRefCount(tmpPtr);
	    break;
	default:
	    Tcl_AppendResult(interp, "(more than one refCount added!)", 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);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (e) concatObj is not a new obj ",
		NULL);

	(void) Tcl_ListObjLength(NULL, concatPtr, &len);
	switch (tmpPtr->refCount) {
	case 3:
	    Tcl_AppendResult(interp, "(failed to concat)", NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(corrupted input!)", 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);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (f) concatObj is not a new obj ",
		NULL);

	(void) Tcl_ListObjLength(NULL, concatPtr, &len);
	switch (tmpPtr->refCount) {
	case 3:
	    Tcl_AppendResult(interp, "(failed to concat)", NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(corrupted input!)", 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);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (g) concatObj is not a new obj ",
		NULL);

	(void) Tcl_ListObjLength(NULL, concatPtr, &len);
	switch (tmpPtr->refCount) {
	case 3:
	    Tcl_AppendResult(interp, "(failed to concat)", NULL);
	    break;
	default:
	    Tcl_AppendResult(interp, "(corrupted input!)", NULL);
	}
	Tcl_DecrRefCount(tmpPtr);
	if (Tcl_IsShared(tmpPtr)) {
	    Tcl_DecrRefCount(tmpPtr);
	}
	tmpPtr = Tcl_DuplicateObj(list1Ptr);
	objv[0] = tmpPtr;







|




|


|


|


|












|




|


|



|


|



|














|




|


|


|


|












|




|


|



|


|



|


















|




|




|


|
















|




|




|


|

















|




|




|


|







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

    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", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (a) concatObj is not a new obj ",
		(char *)NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
	    break;
	default:
	    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", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (b) concatObj is not a new obj ",
		(char *)NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(refCount removed?)", (char *)NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
	    break;
	case 2:
	    Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
	    Tcl_DecrRefCount(tmpPtr);
	    break;
	default:
	    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", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (c) concatObj is not a new obj ",
		(char *)NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
	    break;
	default:
	    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", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (d) concatObj is not a new obj ",
		(char *)NULL);
	switch (tmpPtr->refCount) {
	case 0:
	    Tcl_AppendResult(interp, "(refCount removed?)", (char *)NULL);
	    Tcl_Panic("extremely unsafe behaviour by Tcl_ConcatObj()");
	    break;
	case 1:
	    Tcl_AppendResult(interp, "(no new refCount)", (char *)NULL);
	    break;
	case 2:
	    Tcl_AppendResult(interp, "(refCount added)", (char *)NULL);
	    Tcl_DecrRefCount(tmpPtr);
	    break;
	default:
	    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", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (e) concatObj is not a new obj ",
		(char *)NULL);

	(void) Tcl_ListObjLength(NULL, concatPtr, &len);
	switch (tmpPtr->refCount) {
	case 3:
	    Tcl_AppendResult(interp, "(failed to concat)", (char *)NULL);
	    break;
	default:
	    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", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (f) concatObj is not a new obj ",
		(char *)NULL);

	(void) Tcl_ListObjLength(NULL, concatPtr, &len);
	switch (tmpPtr->refCount) {
	case 3:
	    Tcl_AppendResult(interp, "(failed to concat)", (char *)NULL);
	    break;
	default:
	    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", (char *)NULL);
    }
    if (concatPtr == tmpPtr) {
	result = TCL_ERROR;
	Tcl_AppendResult(interp, "\n\t* (g) concatObj is not a new obj ",
		(char *)NULL);

	(void) Tcl_ListObjLength(NULL, concatPtr, &len);
	switch (tmpPtr->refCount) {
	case 3:
	    Tcl_AppendResult(interp, "(failed to concat)", (char *)NULL);
	    break;
	default:
	    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
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * TestgetencpathObjCmd --
 *
 *	This function implements the "testgetencpath" command. It is used to
 *	test Tcl_GetEncodingSearchPath().
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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;
    }

    Tcl_SetObjResult(interp, Tcl_GetEncodingSearchPath());
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * 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(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */

{






    if (objc != 2) {
        Tcl_WrongNumArgs(interp, 1, objv, "defaultDir");

        return TCL_ERROR;
    }

    Tcl_SetEncodingSearchPath(objv[1]);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * 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;

    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
    };

    foo = 0;
    if (Tcl_ParseArgsObjv(interp, argTable, &count, objv, &remObjv)!=TCL_OK) {
        return TCL_ERROR;
    }
    result[0] = Tcl_NewIntObj(foo);
    result[1] = Tcl_NewIntObj(count);
    result[2] = Tcl_NewListObj(count, remObjv);


    Tcl_SetObjResult(interp, Tcl_NewListObj(3, 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_Command *rPtr)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *varFramePtr = iPtr->varFramePtr;
    Proc *procPtr = (varFramePtr->isProcCallFrame & FRAME_IS_PROC) ?
            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);

        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).
             */

            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).
             */

            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);*/

            } 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;
        }
    }
    return TCL_CONTINUE;
}

static int
InterpVarResolver(
    TCL_UNUSED(Tcl_Interp *),







|

|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<










|
|

|
|
|
>

>
>
>
>
>
>
|
|
>
|


<
>
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









>
|
|
|
|
>
>
|




|

|
|

>
>
|













|





|









|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|

|
|
|
|
|

|
|
|
|







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
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * 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.



 *	Also test for bug [7cb7409e05]







 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static Tcl_Size
ParseMedia(
    TCL_UNUSED(void *),
    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 (Tcl_GetIndexFromObjStruct(interp, objv[0], mediaOpts,
	    sizeof(char *), "media", 0, &index) != TCL_OK) {
	return -1;
    }


    *media = ExtendedMediaOpts[index];
    return 1;
}



















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;
    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;
    }
    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(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_Command *rPtr)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *varFramePtr = iPtr->varFramePtr;
    Proc *procPtr = (varFramePtr->isProcCallFrame & FRAME_IS_PROC) ?
	    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);

	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).
	     */

	    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).
	     */

	    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);*/

	    } 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;
	}
    }
    return TCL_CONTINUE;
}

static int
InterpVarResolver(
    TCL_UNUSED(Tcl_Interp *),
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
} MyResolvedVarInfo;

static inline void
HashVarFree(
    Tcl_Var var)
{
    if (VarHashRefCount(var) < 2) {
        Tcl_Free(var);
    } else {
        VarHashRefCount(var)--;
    }
}

static void
MyCompiledVarFree(
    Tcl_ResolvedVarInfo *vInfoPtr)
{
    MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *) vInfoPtr;

    Tcl_DecrRefCount(resVarInfo->nameObj);
    if (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.
             */

            return var;
        }

        /*
         * The variable is not valid anymore. Clean it up.
         */

        HashVarFree(var);
    }

    hPtr = Tcl_CreateHashEntry((Tcl_HashTable *) &iPtr->globalNsPtr->varTable,
            (char *) resVarInfo->nameObj, &isNewVar);
    if (hPtr) {
        var = (Tcl_Var) TclVarHashGetValue(hPtr);
    } else {
        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_Namespace *),
    Tcl_ResolvedVarInfo **rPtr)
{
    if (*name == 'T') {
 	MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *)Tcl_Alloc(sizeof(MyResolvedVarInfo));

 	resVarInfo->vInfo.fetchProc = MyCompiledVarFetch;







|

|











|



















|
|
|
|

|
|

|
|
|

|



|

|

|
















|







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
} MyResolvedVarInfo;

static inline void
HashVarFree(
    Tcl_Var var)
{
    if (VarHashRefCount(var) < 2) {
	Tcl_Free(var);
    } else {
	VarHashRefCount(var)--;
    }
}

static void
MyCompiledVarFree(
    Tcl_ResolvedVarInfo *vInfoPtr)
{
    MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *) vInfoPtr;

    Tcl_DecrRefCount(resVarInfo->nameObj);
    if (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.
	     */

	    return var;
	}

	/*
	 * The variable is not valid anymore. Clean it up.
	 */

	HashVarFree(var);
    }

    hPtr = Tcl_CreateHashEntry((Tcl_HashTable *) &iPtr->globalNsPtr->varTable,
	    resVarInfo->nameObj, &isNewVar);
    if (hPtr) {
	var = (Tcl_Var) TclVarHashGetValue(hPtr);
    } else {
	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(Tcl_Size) /* length */,
    TCL_UNUSED(Tcl_Namespace *),
    Tcl_ResolvedVarInfo **rPtr)
{
    if (*name == 'T') {
 	MyResolvedVarInfo *resVarInfo = (MyResolvedVarInfo *)Tcl_Alloc(sizeof(MyResolvedVarInfo));

 	resVarInfo->vInfo.fetchProc = MyCompiledVarFetch;
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
TestInterpResolverCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    static const char *const table[] = {
        "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);
	    return TCL_ERROR;
	}
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], table, "operation", TCL_EXACT,
            &idx) != TCL_OK) {
        return TCL_ERROR;
    }
    switch (idx) {
    case 1: /* up */
        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;
        }
    }
    return TCL_OK;
}















































































































































































/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * tab-width: 8
 * indent-tabs-mode: nil
 * End:
 */







|











|




|
|



|
|
|

|
|
|
|
|



|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









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
TestInterpResolverCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    static const char *const table[] = {
	"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", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], table, "operation", TCL_EXACT,
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }
    switch (idx) {
    case 1: /* up */
	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",
		    (char *)NULL);
	    return TCL_ERROR;
	}
    }
    return TCL_OK;
}

/*
 *------------------------------------------------------------------------
 *
 * TestApplyLambdaObjCmd --
 *
 *	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 TestApplyLambdaObjCmd (
    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 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
/*
 * 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.
 *
 * 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 "tclInt.h"
#ifdef TCL_WITH_EXTERNAL_TOMMATH
#   include "tommath.h"
#else
#   include "tclTomMath.h"
#endif
#include "tclStringRep.h"



/*
 * Forward declarations for functions defined later in this file:
 */

static int		CheckIfVarUnset(Tcl_Interp *interp, Tcl_Obj **varPtr, int varIndex);
static int		GetVariableIndex(Tcl_Interp *interp,
			    const char *string, int *indexPtr);
static void		SetVarToObj(Tcl_Obj **varPtr, int 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;


#define VARPTR_KEY "TCLOBJTEST_VARPTR"
#define NUMBER_OF_OBJECT_VARS 20

static void VarPtrDeleteProc(void *clientData, Tcl_Interp *interp)



{
    int i;
    Tcl_Obj **varPtr = (Tcl_Obj **) clientData;
    for (i = 0;  i < NUMBER_OF_OBJECT_VARS;  i++) {

	if (varPtr[i]) Tcl_DecrRefCount(varPtr[i]);
    }
    Tcl_DeleteAssocData(interp, VARPTR_KEY);

    Tcl_Free(varPtr);
}

static Tcl_Obj **GetVarPtr(Tcl_Interp *interp)


{
    Tcl_InterpDeleteProc *proc;

    return (Tcl_Obj **) Tcl_GetAssocData(interp, VARPTR_KEY, &proc);
}

/*








|
|
|





>











>





|

|
|








>




|
>
>
>




>
|
|
<
>



|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*
 * 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 © 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
#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, Tcl_Size varIndex);
static int		GetVariableIndex(Tcl_Interp *interp,
			    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_UNUSED(Tcl_Interp *))
{
    int i;
    Tcl_Obj **varPtr = (Tcl_Obj **) clientData;
    for (i = 0;  i < NUMBER_OF_OBJECT_VARS;  i++) {
	if (varPtr[i]) {
	    Tcl_DecrRefCount(varPtr[i]);
	}

    }
    Tcl_Free(varPtr);
}

static Tcl_Obj **
GetVarPtr(
    Tcl_Interp *interp)
{
    Tcl_InterpDeleteProc *proc;

    return (Tcl_Obj **) Tcl_GetAssocData(interp, VARPTR_KEY, &proc);
}

/*
114
115
116
117
118
119
120




121
122
123
124
125
126
127
    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);




    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TestbignumobjCmd --







>
>
>
>







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    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
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[] = {
	"set", "get", "mult10", "div10", "iseven", "radixsize", NULL
    };
    enum options {
	BIGNUM_SET, BIGNUM_GET, BIGNUM_MULT10, BIGNUM_DIV10, BIGNUM_ISEVEN,
	BIGNUM_RADIXSIZE
    };
    int index, 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) {
	return TCL_ERROR;
    }
    string = Tcl_GetString(objv[2]);
    if (GetVariableIndex(interp, string, &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    varPtr = GetVarPtr(interp);

    switch (index) {
    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) {







|





|
|
>









|


<
|




|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190
191
192
193
194
195
static int
TestbignumobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Tcl interpreter */
    int objc,			/* Argument count */
    Tcl_Obj *const objv[])	/* Argument vector */
{
    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
    } 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,
	    &idx) != TCL_OK) {
	return TCL_ERROR;
    }

    if (GetVariableIndex(interp, objv[2], &varIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    varPtr = GetVarPtr(interp);

    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
	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));
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(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);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(index));
	}
	mp_clear(&bignumValue);
	break;
    }

    Tcl_SetObjResult(interp, varPtr[varIndex]);
    return TCL_OK;







|

|




















|

|







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
	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_SetBooleanObj(varPtr[varIndex], mp_iszero(&bignumValue));
	} else {
	    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_SetWideIntObj(varPtr[varIndex], index);
	} else {
	    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
static int
TestbooleanobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    int varIndex, boolValue;
    const char *index, *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) {
	return TCL_ERROR;
    }

    varPtr = GetVarPtr(interp);

    subCmd = Tcl_GetString(objv[1]);
    if (strcmp(subCmd, "set") == 0) {







>
|
|








<
|







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 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 boolValue;
    const char *subCmd;
    Tcl_Obj **varPtr;

    if (objc < 3) {
	wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }


    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
	 * 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);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(boolValue != 0));
	}
	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) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetWideIntObj(varPtr[varIndex], boolValue == 0);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(boolValue == 0));
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else {
	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
		"bad option \"", Tcl_GetString(objv[1]),
		"\": must be set, get, or not", NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|

|


















|



|

|





|







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
	 * 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_SetBooleanObj(varPtr[varIndex], boolValue);
	} else {
	    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) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetBooleanObj(varPtr[varIndex], !boolValue);
	} else {
	    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", (void *)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
static int
TestdoubleobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int varIndex;
    double doubleValue;
    const char *index, *subCmd, *string;
    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) {
	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, 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







|

|










<
|








|
<







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
static int
TestdoubleobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Size varIndex;
    double doubleValue;
    const char *subCmd;
    Tcl_Obj **varPtr;

    if (objc < 3) {
	wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    varPtr = GetVarPtr(interp);


    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;
	}
	if (Tcl_GetDouble(interp, Tcl_GetString(objv[3]), &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
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetDoubleFromObj(interp, varPtr[varIndex],
				 &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));
	}







|







510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetDoubleFromObj(interp, varPtr[varIndex],
		&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
	} 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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|







539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
	} 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", (void *)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
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;

    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. */
    };
    struct 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) {
	    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);
	}
	return result;
    }

    if (objc < 5) {
	Tcl_AppendToObj(Tcl_GetObjResult(interp), "wrong # args", -1);
	return TCL_ERROR;







|
>








|
|
<
|









|









|







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
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, 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. */
	Tcl_Size offset;		/* Offset between table entries. */
	Tcl_Size index;		/* Selected index into table. */

    } *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_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_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
    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);
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *







|







630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
    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_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
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_WideInt wideValue;
    const char *index, *subCmd, *string;
    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) {
	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) {
	    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);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue));
	}
	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) {
	    return TCL_ERROR;
	}
	intValue = i;
	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], intValue);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue));
	}
    } else if (strcmp(subCmd, "setint") == 0) {
	if (objc != 4) {
	    goto wrongNumArgs;
	}
	string = Tcl_GetString(objv[3]);
	if (Tcl_GetInt(interp, string, &i) != TCL_OK) {
	    return TCL_ERROR;
	}
	intValue = i;
	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetWideIntObj(varPtr[varIndex], intValue);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(intValue));
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else if (strcmp(subCmd, "setmax") == 0) {
	Tcl_WideInt maxWide = WIDE_MAX;
	if (objc != 3) {
	    goto wrongNumArgs;
	}







|
>
>
>

|









<
|








<
|


<










|

|






<
|


<

|

|





<
|


<

|

|







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
static int
TestintobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Size varIndex;
#if (INT_MAX != LONG_MAX)   /* int is not the same size as long */
    int i;
#endif
    Tcl_WideInt wideValue;
    const char *subCmd;
    Tcl_Obj **varPtr;

    if (objc < 3) {
	wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    varPtr = GetVarPtr(interp);

    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;
	}

	if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != 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
	 * 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], wideValue);
	} else {
	    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;
	}

	if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) {
	    return TCL_ERROR;
	}

	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetWideIntObj(varPtr[varIndex], wideValue);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewWideIntObj(wideValue));
	}
    } else if (strcmp(subCmd, "setint") == 0) {
	if (objc != 4) {
	    goto wrongNumArgs;
	}

	if (Tcl_GetWideIntFromObj(interp, objv[3], &wideValue) != TCL_OK) {
	    return TCL_ERROR;
	}

	if ((varPtr[varIndex] != NULL) && !Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetWideIntObj(varPtr[varIndex], wideValue);
	} else {
	    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
    } 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);
    } 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.
	 */







<
|







764
765
766
767
768
769
770

771
772
773
774
775
776
777
778
    } else if (strcmp(subCmd, "get2") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}

	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
    } 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) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], intValue * 10);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue * 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) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetIntObj(varPtr[varIndex], intValue / 10);
	} else {
	    SetVarToObj(varPtr, varIndex, Tcl_NewIntObj(intValue / 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);
	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.





























 *
 * 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[] = {
	"set",
	"get",
	"replace"




    };
    enum listobjCmdIndex {
	LISTOBJ_SET,
	LISTOBJ_GET,
	LISTOBJ_REPLACE



    };

    const char* index;		/* Argument giving the variable number */
    int 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_Obj **varPtr;


    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) {
	return TCL_ERROR;
    }
    if (Tcl_GetIndexFromObj(interp, objv[1], subcommands, "command",
			    0, &cmdIndex) != TCL_OK) {
	return TCL_ERROR;
    }
    switch(cmdIndex) {







|
|



|

|









|
|



|

|





|













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















|


|
>
>
>
>




|
>
>
>
|

<
|
<
|
|

>






<
|







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
    } else if (strcmp(subCmd, "mult10") == 0) {
	if (objc != 3) {
	    goto wrongNumArgs;
	}
	if (CheckIfVarUnset(interp, varPtr,varIndex)) {
	    return TCL_ERROR;
	}
	if (Tcl_GetWideIntFromObj(interp, varPtr[varIndex],
		&wideValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetWideIntObj(varPtr[varIndex], wideValue * 10);
	} else {
	    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_GetWideIntFromObj(interp, varPtr[varIndex],
		&wideValue) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (!Tcl_IsShared(varPtr[varIndex])) {
	    Tcl_SetWideIntObj(varPtr[varIndex], wideValue / 10);
	} else {
	    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", (void *)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 */
    static const char* const subcommands[] = {
	"set",
	"get",
	"replace",
	"indexmemcheck",
	"getelementsmemcheck",
	"index",
	NULL
    };
    enum listobjCmdIndex {
	LISTOBJ_SET,
	LISTOBJ_GET,
	LISTOBJ_REPLACE,
	LISTOBJ_INDEXMEMCHECK,
	LISTOBJ_GETELEMENTSMEMCHECK,
	LISTOBJ_INDEX,
    } cmdIndex;


    Tcl_Size varIndex;		/* Variable number converted to binary */

    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);

    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
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
	break;

    case LISTOBJ_REPLACE:
	if (objc < 5) {
	    Tcl_WrongNumArgs(interp, 2, objv,
			     "varIndex start count ?element...?");
	    return TCL_ERROR;
	}
	if (Tcl_GetIntFromObj(interp, objv[3], &first) != TCL_OK
	    || Tcl_GetIntFromObj(interp, objv[4], &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);






































































    }
    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 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;
    const Tcl_ObjType *targetType;
    Tcl_Obj **varPtr;














    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 (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;

	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_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;
	}
	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) {
	    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;
	}
	Tcl_InvalidateStringRep(varPtr[varIndex]);
	Tcl_SetObjResult(interp, varPtr[varIndex]);
    } else if (strcmp(subCmd, "newobj") == 0) {

	if (objc != 3) {
	    goto wrongNumArgs;




	}
	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]);
    } else if (strcmp(subCmd, "objtype") == 0) {
	const char *typeName;



	/*
	 * Return an object containing the name of the argument's type of
	 * internal rep. If none exists, return "none".
	 */

	if (objc != 3) {
	    goto wrongNumArgs;


	}
	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 (!strcmp(typeName, "wideInt")) typeName = "int";
#endif
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1));
	}





















    } 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;
	}




	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(varPtr[varIndex]->refCount));
    } else if (strcmp(subCmd, "type") == 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;
















	}
	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),
		    "int", -1);
#endif
	} else {
	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
		    varPtr[varIndex]->typePtr->name, -1);
	}
    } else if (strcmp(subCmd, "types") == 0) {
	if (objc != 2) {
	    goto wrongNumArgs;
	}
	if (Tcl_AppendAllObjTypes(interp,
		Tcl_GetObjResult(interp)) != TCL_OK) {
	    return TCL_ERROR;
	}
    } 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 --







|


|
|







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|
|


>
>
>
>
>
>
>
>
>
>
>
>
>








<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<









|
>
|

|
>
|
>
>
>
>
|
<

<
|
<
<
<
<
>


>
>
>
>

<
<
|
>
>
>
|
|
>
|
<
<
|
>
>







>
>
|
|
|
|
|
>
>

|


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|


>
|
>
>
>
>
>
>
>
>


>
>
>
>
|
<
>
>
|


<
|


>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|
<
<
<
<
|
|
|
<
<
<
<
<
<
|







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
	}
	Tcl_SetObjResult(interp, varPtr[varIndex]);
	break;

    case LISTOBJ_REPLACE:
	if (objc < 5) {
	    Tcl_WrongNumArgs(interp, 2, objv,
		    "varIndex start count ?element...?");
	    return TCL_ERROR;
	}
	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);

    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. */
{
    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);





    if (Tcl_GetIndexFromObj(

























	    interp, objv[1], subcommands, "command", 0, &cmdIndex)

















	!= TCL_OK) {
	return TCL_ERROR;
    }






    switch (cmdIndex) {
    case TESTOBJ_FREEALLVARS:











	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;
	    }
	}
	return TCL_OK;
    case TESTOBJ_BUG3598580:
	if (objc != 2) {
	    goto wrongNumArgs;
	} 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_OK;




    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);
	}


	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);


	}
	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;
		if (!strcmp(typeName, "utf32string"))
		    typeName = "string";
#ifndef TCL_WIDE_INT_IS_LONG
	    else if (!strcmp(typeName, "wideInt")) typeName = "int";
#endif
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(typeName, -1));
	    }
	}
	return TCL_OK;
    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;

    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, 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),
		    "no type ", Tcl_GetString(objv[3]), " found", (void *)NULL);
	    return TCL_ERROR;
	}
	if (Tcl_ConvertToType(interp, varPtr[varIndex], targetType)
		!= TCL_OK) {
	    return TCL_ERROR;
	}
	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;
	}
	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);
#ifndef TCL_WIDE_INT_IS_LONG
	} else if (!strcmp(varPtr[varIndex]->typePtr->name, "wideInt")) {
	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
		    "int", -1);
#endif
	} else {
	    Tcl_AppendToObj(Tcl_GetObjResult(interp),
		    varPtr[varIndex]->typePtr->name, -1);
	}
	break;




    default:
	break;
    }







    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
TeststringobjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_UniChar *unicode;

    int varIndex, option, i, length;

#define MAX_STRINGS 11
    const char *index, *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
    };

    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) {
	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) {
		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_SetObjResult(interp, varPtr[varIndex]);
	    break;
	case 1:				/* appendstrings */
	    if (objc > (MAX_STRINGS+3)) {
		goto wrongNumArgs;
	    }
	    if (varPtr[varIndex] == NULL) {







>
|
>

|




|
|









<
|












|














<
|







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
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 option, i;
    Tcl_Size length;
#define MAX_STRINGS 11
    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", "range", "appendself",
	"appendself2", "newunicode", NULL
    };

    if (objc < 3) {
	wrongNumArgs:
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    varPtr = GetVarPtr(interp);

    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_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]));
	    }

	    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
	    }
	    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]);
	    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);
	    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;
	    } else {
		length = -1;
	    }
	    Tcl_SetIntObj(Tcl_GetObjResult(interp), length);
	    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);
	    if ((varPtr[varIndex] != NULL)
		    && !Tcl_IsShared(varPtr[varIndex])) {
		Tcl_SetStringObj(varPtr[varIndex], string, length);
	    } else {
		SetVarToObj(varPtr, varIndex, Tcl_NewStringObj(string, length));
	    }
	    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) {
		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;
	    }
	    Tcl_SetIntObj(Tcl_GetObjResult(interp), length);
	    break;












	case 10:			/* 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);

	    if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if ((i < 0) || (i > length)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"index value out of range", -1));
		return TCL_ERROR;
	    }

	    Tcl_AppendToObj(varPtr[varIndex], string + i, length - i);
	    Tcl_SetObjResult(interp, varPtr[varIndex]);
	    break;
	case 11:			/* 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);

	    if (Tcl_GetIntFromObj(interp, objv[3], &i) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if ((i < 0) || (i > length)) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"index value out of range", -1));
		return TCL_ERROR;
	    }

	    TclAppendUnicodeToObj(varPtr[varIndex], unicode + i, length - i);
	    Tcl_SetObjResult(interp, varPtr[varIndex]);

















	    break;
    }

    return TCL_OK;
}







































































































































/*
 *----------------------------------------------------------------------
 *
 * SetVarToObj --
 *
 *	Utility routine to assign a Tcl_Obj* to a test variable. The
 *	Tcl_Obj* can be NULL.







|


















<
|
















|

|

|















|


|

|













|
















|

|

>
>
>
>
>
>
>
>
>
>
>
>
|
















|

|


|





|


|
















|

|


|





|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    }
	    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], (void *)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;
	    }

	    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 = strPtr->allocated;
	    } else {
		length = TCL_INDEX_NONE;
	    }
	    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], &size);
	    if ((varPtr[varIndex] != NULL)
		    && !Tcl_IsShared(varPtr[varIndex])) {
		Tcl_SetStringObj(varPtr[varIndex], string, size);
	    } else {
		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_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 = TCL_INDEX_NONE;
	    }
	    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 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], &size);

	    if (Tcl_GetIntForIndex(interp, objv[3], size-1, &length) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (length == TCL_INDEX_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"index value out of range", -1));
		return TCL_ERROR;
	    }

	    Tcl_AppendToObj(varPtr[varIndex], string + length, size - length);
	    Tcl_SetObjResult(interp, varPtr[varIndex]);
	    break;
	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], &size);

	    if (Tcl_GetIntForIndex(interp, objv[3], size-1, &length) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (length == TCL_INDEX_NONE) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"index value out of range", -1));
		return TCL_ERROR;
	    }

	    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
 *
 *----------------------------------------------------------------------
 */

static void
SetVarToObj(
    Tcl_Obj **varPtr,
    int 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) {







|







1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
 *
 *----------------------------------------------------------------------
 */

static void
SetVarToObj(
    Tcl_Obj **varPtr,
    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
 *
 *----------------------------------------------------------------------
 */

static int
GetVariableIndex(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    const char *string,		/* String containing a variable index
				 * specified as a nonnegative number less than
				 * NUMBER_OF_OBJECT_VARS. */
    int *indexPtr)		/* Place to store converted result. */
{
    int index;

    if (Tcl_GetInt(interp, string, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    if (index < 0 || index >= NUMBER_OF_OBJECT_VARS) {
	Tcl_ResetResult(interp);
	Tcl_AppendToObj(Tcl_GetObjResult(interp), "bad variable index", -1);
	return TCL_ERROR;
    }

    *indexPtr = index;
    return TCL_OK;







|


|

|

|


|







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
GetVariableIndex(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Tcl_Obj *obj,		/* The variable index
				 * specified as a nonnegative number less than
				 * NUMBER_OF_OBJECT_VARS. */
    Tcl_Size *indexPtr)		/* Place to store converted result. */
{
    Tcl_Size index;

    if (Tcl_GetIntForIndex(interp, obj, NUMBER_OF_OBJECT_VARS - 1, &index) != TCL_OK) {
	return TCL_ERROR;
    }
    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
 *----------------------------------------------------------------------
 */

static int
CheckIfVarUnset(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Tcl_Obj ** varPtr,
    int varIndex)		/* Index of the test variable to check. */
{
    if (varPtr[varIndex] == NULL) {
	char buf[32 + TCL_INTEGER_SPACE];

	sprintf(buf, "variable %d is unset (NULL)", varIndex);
	Tcl_ResetResult(interp);
	Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1);
	return 1;
    }
    return 0;
}








|

|


|







1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
 *----------------------------------------------------------------------
 */

static int
CheckIfVarUnset(
    Tcl_Interp *interp,		/* Interpreter for error reporting. */
    Tcl_Obj ** varPtr,
    Tcl_Size varIndex)		/* Index of the test variable to check. */
{
    if (varIndex < 0 || varPtr[varIndex] == NULL) {
	char buf[32 + TCL_INTEGER_SPACE];

	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
/*
 * 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.
 *
 * 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 "tclInt.h"

/*
 * name and version of this package
 */

static const char packageName[] = "procbodytest";
static const char packageVersion[] = "1.1";

/*
 * Name of the commands exported by this package
 */

static const char procCommand[] = "proc";







|





>
>









|







1
2
3
4
5
6
7
8
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 © 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[] = "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
    int exportIt;		/* if 1, export the command */
} CmdTable;

/*
 * Declarations for functions defined in this file.
 */

static int	ProcBodyTestProcObjCmd(void *dummy,
			Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
static int	ProcBodyTestCheckObjCmd(void *dummy,
			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.







|
<
|
<







43
44
45
46
47
48
49
50

51

52
53
54
55
56
57
58
    int exportIt;		/* if 1, export the command */
} CmdTable;

/*
 * Declarations for functions defined in this file.
 */

static Tcl_ObjCmdProc ProcBodyTestProcObjCmd;

static Tcl_ObjCmdProc ProcBodyTestCheckObjCmd;

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.
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
};

/*
 *----------------------------------------------------------------------
 *
 * Procbodytest_Init --
 *
 *	This function initializes the "procbodytest" package.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	None.
 *







|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
};

/*
 *----------------------------------------------------------------------
 *
 * Procbodytest_Init --
 *
 *	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
}

/*
 *----------------------------------------------------------------------
 *
 * Procbodytest_SafeInit --
 *
 *	This function initializes the "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
}

/*
 *----------------------------------------------------------------------
 *
 * Procbodytest_SafeInit --
 *
 *	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
    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 }",
		namesp, cmdTablePtr->cmdName);
	if (Tcl_EvalEx(interp, buf, -1, 0) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    sprintf(buf, "%s::%s", namesp, cmdTablePtr->cmdName);
    Tcl_CreateObjCommand(interp, buf, cmdTablePtr->proc, 0, 0);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|

|




|







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) {
	snprintf(buf, sizeof(buf), "namespace eval %s { namespace export %s }",
		namesp, cmdTablePtr->cmdName);
	if (Tcl_EvalEx(interp, buf, TCL_INDEX_NONE, 0) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    snprintf(buf, sizeof(buf), "%s::%s", namesp, cmdTablePtr->cmdName);
    Tcl_CreateObjCommand(interp, buf, cmdTablePtr->proc, 0, 0);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
    /*
     * 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);
	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);
	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);
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(bodyObjPtr);

    myobjv[0] = objv[0];
    myobjv[1] = objv[1];
    myobjv[2] = objv[2];







|










|











|







261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
    /*
     * 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", (void *)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!", (void *)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, "\"", (void *)NULL);
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(bodyObjPtr);

    myobjv[0] = objv[0];
    myobjv[1] = objv[1];
    myobjv[2] = objv[2];
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
 * ProcBodyTestCheckObjCmd --
 *
 *  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
 *  was provided.  Places a boolean in the interp result indicating the
 *  test outcome.
 *
 * Results:
 *  Returns a standard Tcl code.
 *
 *----------------------------------------------------------------------







|







311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
 * ProcBodyTestCheckObjCmd --
 *
 *  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 tcl::procbodytest package
 *  was provided.  Places a boolean in the interp result indicating the
 *  test outcome.
 *
 * Results:
 *  Returns a standard Tcl code.
 *
 *----------------------------------------------------------------------
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }

    version = Tcl_PkgPresentEx(interp, packageName, packageVersion, 1, NULL);
    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
	    strcmp(version, packageVersion) == 0));
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|











336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354

    if (objc != 1) {
	Tcl_WrongNumArgs(interp, 1, objv, "");
	return TCL_ERROR;
    }

    version = Tcl_PkgPresentEx(interp, packageName, packageVersion, 1, NULL);
    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
/*
 * 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
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|
|







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 © 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
 *
 *----------------------------------------------------------------------
 */

void *
Tcl_GetThreadData(
    Tcl_ThreadDataKey *keyPtr,	/* Identifier for the data chunk */
    size_t 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;
	RememberSyncObject(keyPtr, &keyRecord);
    } else {
	result = *keyPtr;
    }
#endif /* TCL_THREADS */
    return result;
}







|


















|







57
58
59
60
61
62
63
64
65
66
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 */
    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 = (Tcl_ThreadDataKey)result;
	RememberSyncObject(keyPtr, &keyRecord);
    } else {
	result = *keyPtr;
    }
#endif /* TCL_THREADS */
    return result;
}
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
 *
 *----------------------------------------------------------------------
 */

#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 */
{
}

#undef Tcl_ConditionNotify
void
Tcl_ConditionNotify(
    Tcl_Condition *condPtr)
{
}

#undef Tcl_MutexLock
void
Tcl_MutexLock(
    Tcl_Mutex *mutexPtr)
{
}

#undef Tcl_MutexUnlock
void
Tcl_MutexUnlock(
    Tcl_Mutex *mutexPtr)
{
}
#endif /* !TCL_THREADS */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|
|
|






|






|






|











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
 *
 *----------------------------------------------------------------------
 */

#undef Tcl_ConditionWait
void
Tcl_ConditionWait(
    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_UNUSED(Tcl_Condition *))
{
}

#undef Tcl_MutexLock
void
Tcl_MutexLock(
    TCL_UNUSED(Tcl_Mutex *))
{
}

#undef Tcl_MutexUnlock
void
Tcl_MutexUnlock(
    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
/*
 * 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.
 *
 * 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)








|







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 © 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)
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
    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 */
} 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 */
    Tcl_Obj *lastPtr;		/* Last object in this cache */
    int 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.
 */







<

|













|

|







87
88
89
90
91
92
93

94
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 numLocks;		/* Number of locks acquired */
    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 */
    size_t numObjects;		/* Number of objects for thread */
    Tcl_Obj *lastPtr;		/* Last object in this cache */
    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
/*
 * 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 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);

/*
 * Local variables defined in this file and initialized at startup.
 */

static Tcl_Mutex *listLockPtr;
static Tcl_Mutex *objLockPtr;







|


|
|
|







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, size_t numMove);
static int	GetBlocks(Cache *cachePtr, int bucket);
static Block *	Ptr2Block(void *ptr);
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;
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

    /*
     * Get this thread's obj list structure and move or allocate new objs if
     * necessary.
     */

    if (cachePtr->numObjects == 0) {
	int 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);
	    }
	    cachePtr->lastPtr = newObjsPtr + numMove - 1;
	    objPtr = cachePtr->firstObjPtr;	/* NULL */
	    while (--numMove >= 0) {
		newObjsPtr[numMove].internalRep.twoPtrValue.ptr1 = objPtr;
		objPtr = newObjsPtr + numMove;
	    }
	    cachePtr->firstObjPtr = newObjsPtr;
	}
    }








|
















|



|







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) {
	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 %" TCL_Z_MODIFIER "u new objects", numMove);
	    }
	    cachePtr->lastPtr = newObjsPtr + numMove - 1;
	    objPtr = cachePtr->firstObjPtr;	/* NULL */
	    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
    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);
	    Tcl_DStringAppendElement(dsPtr, buf);
	}
	for (n = 0; n < NBUCKETS; ++n) {

	    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",
		    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].numWaits);
	    Tcl_DStringAppendElement(dsPtr, buf);
	}
	Tcl_DStringEndSublist(dsPtr);
	cachePtr = cachePtr->nextPtr;
    }
    Tcl_MutexUnlock(listLockPtr);
}







|



>
|





|
<







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 {
	    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 %"
		    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);

	    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
 *----------------------------------------------------------------------
 */

static void
MoveObjs(
    Cache *fromPtr,
    Cache *toPtr,
    int 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) {
	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.







|












|







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,
    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-- > 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
 *
 *----------------------------------------------------------------------
 */

static void
PutObjs(
    Cache *fromPtr,
    int numMove)
{
    int 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);
	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.
     */







|

|










|







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,
    size_t 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-- > 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
 *----------------------------------------------------------------------
 */

static void *
Block2Ptr(
    Block *blockPtr,
    int bucket,
    unsigned int reqSize)
{
    void *ptr;

    blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC;
    blockPtr->sourceBucket = bucket;
    blockPtr->blockReqSize = reqSize;
    ptr = ((void *) (blockPtr + 1));







|







777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
 *----------------------------------------------------------------------
 */

static void *
Block2Ptr(
    Block *blockPtr,
    int bucket,
    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
 *----------------------------------------------------------------------
 */

static void
PutBlocks(
    Cache *cachePtr,
    int bucket,
    int numMove)
{
    /*
     * We have numFree.  Want to shed numMove. So compute how many
     * Blocks to keep.
     */

    int 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);
	lastPtr->nextBlock = NULL;
    }

    /*
     * Aquire the lock and place the list of blocks at the front of the shared
     * cache bucket.
     */







|






|










|







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,
    size_t numMove)
{
    /*
     * We have numFree.  Want to shed numMove. So compute how many
     * Blocks to keep.
     */

    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-- > 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
    Cache *cachePtr,
    int bucket)
{
    Block *blockPtr;
    size_t n;

    /*
     * First, atttempt 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);







|







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, 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
		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) {
		    blockPtr = blockPtr->nextBlock;
		}
		sharedPtr->buckets[bucket].firstPtr = blockPtr->nextBlock;
		cachePtr->buckets[bucket].lastPtr = blockPtr;
		blockPtr->nextBlock = NULL;
	    }
	}







|







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-- > 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
	 * 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) {
	    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;
	    }







|







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 + 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
	/*
	 * 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) {
	    blockPtr->nextBlock = (Block *)
		((char *) blockPtr + bucketInfo[bucket].blockSize);
	    blockPtr = blockPtr->nextBlock;
	}
	cachePtr->buckets[bucket].lastPtr = blockPtr;
	blockPtr->nextBlock = NULL;
    }







|







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-- > 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

    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;
	bucketInfo[i].lockPtr = TclpNewAllocMutex();
    }
    TclpInitAllocCache();
}

/*
 *----------------------------------------------------------------------







|







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 ?
		(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
/*
 * 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
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"









|







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 © 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
}

/*
 *----------------------------------------------------------------------
 *
 * TclRememberJoinableThread --
 *
 *	This procedure remebers a thread as joinable. Only a call to
 *	TclJoinThread will remove the structre 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.







|
|







207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
}

/*
 *----------------------------------------------------------------------
 *
 * TclRememberJoinableThread --
 *
 *	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

    if (threadPtr->waitedUpon) {
	Tcl_ConditionNotify(&threadPtr->cond);
    }

    Tcl_MutexUnlock(&threadPtr->threadMutex);
}


#endif /* _WIN32 */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>









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
/*
 * 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
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|
|







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 © 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
} 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. */
    sig_atomic_t allocated;	/* The size of the table in the current
				 * thread. */
} TSDTable;

/*
 * The actual type of Tcl_ThreadDataKey.
 */







|







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 {
    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
 */

void *
TclThreadStorageKeyGet(
    Tcl_ThreadDataKey *dataKeyPtr)
{
    TSDTable *tsdTablePtr = (TSDTable *)TclpThreadGetGlobalTSD(tsdGlobal.key);
    ClientData resultPtr = NULL;
    TSDUnion *keyPtr = (TSDUnion *) dataKeyPtr;
    sig_atomic_t offset = keyPtr->offset;

    if ((tsdTablePtr != NULL) && (offset > 0)
	    && (offset < tsdTablePtr->allocated)) {
	resultPtr = tsdTablePtr->tablePtr[offset];
    }







|







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);
    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
/*
 * 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.
 *
 * 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 "tclInt.h"

#if TCL_THREADS
/*








|
|





>
>







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 © 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
/*
 * 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 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);







|
<
<







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 Tcl_ObjCmdProc ThreadObjCmd;


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);
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
ThreadObjCmd(
    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
    };

    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) {







<









|







207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
ThreadObjCmd(
    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);

    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
	Tcl_MutexLock(&threadMutex);
	tsdPtr->interp = interp;
	ListUpdateInner(tsdPtr);
	Tcl_CreateThreadExitHandler(ThreadExitProc, NULL);
	Tcl_MutexUnlock(&threadMutex);
    }

    switch ((enum options)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?");







|







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 (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
	}
	arg++;
	if (arg < objc) {
	    result = Tcl_GetString(objv[arg]);
	} else {
	    result = NULL;
	}
	return ThreadCancel(interp, (Tcl_ThreadId) (size_t) id, result, flags);
    }
    case THREAD_CREATE: {
	const char *script;
	int joinable, len;


	if (objc == 2) {
	    /*
	     * Neither joinable nor special script
	     */

	    joinable = 0;







|



|
>







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) INT2PTR(id), result, flags);
    }
    case THREAD_CREATE: {
	const char *script;
	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
	    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());
	    } else if (objc == 3
		    && strcmp("-main", Tcl_GetString(objv[2])) == 0) {
		Tcl_MutexLock(&threadMutex);
		idObj = Tcl_NewWideIntObj((Tcl_WideInt)(size_t)mainThreadId);
		Tcl_MutexUnlock(&threadMutex);
	    } else {
		Tcl_WrongNumArgs(interp, 2, objv, NULL);
		return TCL_ERROR;
	    }

	    Tcl_SetObjResult(interp, idObj);







|



|







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)PTR2INT(Tcl_GetCurrentThread()));
	    } else if (objc == 3
		    && strcmp("-main", Tcl_GetString(objv[2])) == 0) {
		Tcl_MutexLock(&threadMutex);
		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
	    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);
	if (result == TCL_OK) {
	    Tcl_SetIntObj(Tcl_GetObjResult(interp), status);
	} else {
	    char buf[20];

	    sprintf(buf, "%" TCL_LL_MODIFIER "d", id);
	    Tcl_AppendResult(interp, "cannot join thread ", buf, NULL);
	}
	return result;
    }
    case THREAD_NAMES:
	if (objc > 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;







|



|

|
|







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)INT2PTR(id), &status);
	if (result == TCL_OK) {
	    Tcl_SetIntObj(Tcl_GetObjResult(interp), status);
	} else {
	    char buf[TCL_INTEGER_SPACE];

	    snprintf(buf, sizeof(buf), "%" TCL_LL_MODIFIER "d", (long long)id);
	    Tcl_AppendResult(interp, "cannot join thread ", buf, (void *)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
	    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);
    }
    case THREAD_EVENT: {
	if (objc > 2) {
	    Tcl_WrongNumArgs(interp, 2, objv, NULL);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj(







|







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)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

    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);
	return TCL_ERROR;
    }

    /*
     * Wait for the thread to start because it is using something on our stack!
     */








|







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", (void *)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
    Tcl_MutexUnlock(&threadMutex);

    /*
     * Run the script.
     */

    Tcl_Preserve(tsdPtr->interp);
    result = Tcl_EvalEx(tsdPtr->interp, threadEvalScript, -1, 0);
    if (result != TCL_OK) {
	ThreadErrorProc(tsdPtr->interp);
    }

    /*
     * Clean up.
     */







|







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, 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
    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());

    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);







|







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];

    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
	if (tsdPtr->threadId == threadId) {
	    found = 1;
	    break;
	}
    }
    if (!found) {
	Tcl_MutexUnlock(&threadMutex);
	Tcl_AppendResult(interp, "invalid thread id", NULL);
	return TCL_ERROR;
    }

    /*
     * Short circut 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);
    }







|




|







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", (void *)NULL);
	return TCL_ERROR;
    }

    /*
     * 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

    /*
     * Queue the event and poke the other thread's notifier.
     */

    threadEventPtr->event.proc = ThreadEventProc;
    Tcl_ThreadQueueEvent(threadId, (Tcl_Event *) threadEventPtr,
	    TCL_QUEUE_TAIL);
    Tcl_ThreadAlert(threadId);

    if (!wait) {
	Tcl_MutexUnlock(&threadMutex);
	return TCL_OK;
    }

    /*







|
<







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_ALERT_IF_EMPTY);


    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
    resultPtr->nextPtr = NULL;
    resultPtr->prevPtr = NULL;

    Tcl_MutexUnlock(&threadMutex);

    if (resultPtr->code != TCL_OK) {
	if (resultPtr->errorCode) {
	    Tcl_SetErrorCode(interp, resultPtr->errorCode, NULL);
	    Tcl_Free(resultPtr->errorCode);
	}
	if (resultPtr->errorInfo) {
	    Tcl_AddErrorInfo(interp, resultPtr->errorInfo);
	    Tcl_Free(resultPtr->errorInfo);
	}
    }
    Tcl_AppendResult(interp, resultPtr->result, NULL);
    Tcl_ConditionFinalize(&resultPtr->done);
    code = resultPtr->code;

    Tcl_Free(resultPtr->result);
    Tcl_Free(resultPtr);

    return code;







|







|







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, (void *)NULL);
	    Tcl_Free(resultPtr->errorCode);
	}
	if (resultPtr->errorInfo) {
	    Tcl_AddErrorInfo(interp, resultPtr->errorInfo);
	    Tcl_Free(resultPtr->errorInfo);
	}
    }
    Tcl_AppendResult(interp, resultPtr->result, (void *)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
	if (tsdPtr->threadId == threadId) {
	    found = 1;
	    break;
	}
    }
    if (!found) {
	Tcl_MutexUnlock(&threadMutex);
	Tcl_AppendResult(interp, "invalid thread id", NULL);
	return TCL_ERROR;
    }

    /*
     * Since Tcl_CancelEval can be safely called from any thread,
     * we do it now.
     */







|







969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
	if (tsdPtr->threadId == threadId) {
	    found = 1;
	    break;
	}
    }
    if (!found) {
	Tcl_MutexUnlock(&threadMutex);
	Tcl_AppendResult(interp, "invalid thread id", (void *)NULL);
	return TCL_ERROR;
    }

    /*
     * Since Tcl_CancelEval can be safely called from any thread,
     * we do it now.
     */

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
/*
 * tclTimer.c --
 *
 *	This file provides timer event management facilities for Tcl,
 *	including the "after" command.
 *
 * Copyright (c) 1997 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.
 */

#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. */
    Tcl_TimerToken token;	/* Identifies handler so it can be deleted. */
    struct TimerHandler *nextPtr;
				/* Next event in queue, or NULL for end of
				 * queue. */
} TimerHandler;

/*






|
















|







1
2
3
4
5
6
7
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 © 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. */
    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
 * 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. */
    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







|







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. */
    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
 * 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);
 */

#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)

#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)

/*
 * 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,
			    Tcl_Interp *interp);
static int		AfterDelay(Tcl_Interp *interp, Tcl_WideInt ms);
static void		AfterProc(ClientData clientData);
static void		FreeAfterPtr(AfterInfo *afterPtr);
static AfterInfo *	GetAfterEvent(AfterAssocData *assocPtr,
			    Tcl_Obj *commandPtr);
static ThreadSpecificData *InitTimer(void);
static void		TimerExitProc(ClientData clientData);
static int		TimerHandlerEventProc(Tcl_Event *evPtr, int flags);
static void		TimerCheckProc(ClientData clientData, int flags);
static void		TimerSetupProc(ClientData clientData, int flags);

/*
 *----------------------------------------------------------------------
 *
 * InitTimer --
 *
 *	This function initializes the timer module.







|







|



|




















|


|




|

|
|







113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
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 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) + \
	    ((t1).usec - (t2).usec)/1000)

#define TCL_TIME_DIFF_MS_CEILING(t1, t2) \
    (1000*((Tcl_WideInt)(t1).sec - (Tcl_WideInt)(t2).sec) + \
	    ((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(void *clientData,
			    Tcl_Interp *interp);
static int		AfterDelay(Tcl_Interp *interp, Tcl_WideInt ms);
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(void *clientData);
static int		TimerHandlerEventProc(Tcl_Event *evPtr, 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
 *	Removes the timer and idle event sources and remaining events.
 *
 *----------------------------------------------------------------------
 */

static void
TimerExitProc(
    TCL_UNUSED(ClientData))
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

    Tcl_DeleteEventSource(TimerSetupProc, TimerCheckProc, NULL);
    if (tsdPtr != NULL) {
	TimerHandler *timerHandlerPtr;








|







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(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
 */

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. */
{
    Tcl_Time time;

    /*
     * Compute when the event should fire.
     */








|







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. */
    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
 *--------------------------------------------------------------
 */

Tcl_TimerToken
TclCreateAbsoluteTimerHandler(
    Tcl_Time *timePtr,
    Tcl_TimerProc *proc,
    ClientData clientData)
{
    TimerHandler *timerHandlerPtr, *tPtr2, *prevPtr;
    ThreadSpecificData *tsdPtr = InitTimer();

    timerHandlerPtr = (TimerHandler *)Tcl_Alloc(sizeof(TimerHandler));

    /*







|







288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
 *--------------------------------------------------------------
 */

Tcl_TimerToken
TclCreateAbsoluteTimerHandler(
    Tcl_Time *timePtr,
    Tcl_TimerProc *proc,
    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
 *	May update the maximum notifier block time.
 *
 *----------------------------------------------------------------------
 */

static void
TimerSetupProc(
    TCL_UNUSED(ClientData),
    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)) {







|







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(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
 *	May queue an event and update the maximum notifier block time.
 *
 *----------------------------------------------------------------------
 */

static void
TimerCheckProc(
    TCL_UNUSED(ClientData),
    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) {







|







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(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
 *
 *--------------------------------------------------------------
 */

void
Tcl_DoWhenIdle(
    Tcl_IdleProc *proc,		/* Function to invoke. */
    ClientData clientData)	/* Arbitrary value to pass to proc. */
{
    IdleHandler *idlePtr;
    Tcl_Time blockTime;
    ThreadSpecificData *tsdPtr = InitTimer();

    idlePtr = (IdleHandler *)Tcl_Alloc(sizeof(IdleHandler));
    idlePtr->proc = proc;







|







615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
 *
 *--------------------------------------------------------------
 */

void
Tcl_DoWhenIdle(
    Tcl_IdleProc *proc,		/* Function to invoke. */
    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
 *
 *----------------------------------------------------------------------
 */

void
Tcl_CancelIdleCall(
    Tcl_IdleProc *proc,		/* Function that was previously registered. */
    ClientData 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) {







|







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. */
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_AfterObjCmd(
    TCL_UNUSED(ClientData),
    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;
    int index = -1;
    static const char *const afterSubCmds[] = {
	"cancel", "idle", "info", NULL
    };
    enum afterSubCmdsEnum {AFTER_CANCEL, AFTER_IDLE, AFTER_INFO};
    ThreadSpecificData *tsdPtr = InitTimer();








|








|







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(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;
    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
	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 (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0, &index)
		!= TCL_OK) {
            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);
	    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.







|


|





|







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 (TclGetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK) {
	if (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0, &index)
		!= TCL_OK) {
	    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, (void *)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
	 * 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;
	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;

	if (objc < 3) {
	    Tcl_WrongNumArgs(interp, 2, objv, "id|command");
	    return TCL_ERROR;
	}
	if (objc == 3) {
	    commandPtr = objv[2];







|
|














|







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 += 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;
	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
	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_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]);

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "event \"%s\" doesn't exist", eventStr));
            Tcl_SetErrorCode(interp, "TCL","LOOKUP","EVENT", eventStr, NULL);
	    return TCL_ERROR;
	} else {
            Tcl_Obj *resultListPtr;

            TclNewObj(resultListPtr);
            Tcl_ListObjAppendElement(interp, resultListPtr,
                    afterPtr->commandPtr);
            Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
		    (afterPtr->token == NULL) ? "idle" : "timer", -1));
            Tcl_SetObjResult(interp, resultListPtr);
        }
	break;
    default:
	Tcl_Panic("Tcl_AfterObjCmd: bad subcommand index to afterSubCmds");
    }
    return TCL_OK;
}








|
|















|


|

|
|
|
|


|







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_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]);

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                    "event \"%s\" doesn't exist", eventStr));
            Tcl_SetErrorCode(interp, "TCL","LOOKUP","EVENT", eventStr, (void *)NULL);
	    return TCL_ERROR;
	} else {
	    Tcl_Obj *resultListPtr;

	    TclNewObj(resultListPtr);
	    Tcl_ListObjAppendElement(interp, resultListPtr,
		    afterPtr->commandPtr);
	    Tcl_ListObjAppendElement(interp, resultListPtr, Tcl_NewStringObj(
		    (afterPtr->token == NULL) ? "idle" : "timer", -1));
            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
    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;
    if (endTime.usec >= 1000000) {
	endTime.sec++;
	endTime.usec -= 1000000;
    }

    do {
	if (Tcl_AsyncReady()) {







|
|







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 += (ms / 1000);
    endTime.usec += (ms % 1000) * 1000;
    if (endTime.usec >= 1000000) {
	endTime.sec++;
	endTime.usec -= 1000000;
    }

    do {
	if (Tcl_AsyncReady()) {
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
	    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_Sleep((long) diff);
                if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) {
                    break;
                }
	    } else {
                break;
            }
	} else {







|







1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
	    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_Sleep((int) diff);
                if (diff < SLEEP_OFFLOAD_GETTIMEOFDAY) {
                    break;
                }
	    } else {
                break;
            }
	} else {
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. */
{
    AfterInfo *afterPtr = (AfterInfo *)clientData;
    AfterAssocData *assocPtr = afterPtr->assocPtr;
    AfterInfo *prevPtr;
    int result;
    Tcl_Interp *interp;








|







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(
    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
 *	After commands are removed.
 *
 *----------------------------------------------------------------------
 */

static void
AfterCleanupProc(
    ClientData clientData,	/* Points to AfterAssocData for the
				 * interpreter. */
    TCL_UNUSED(Tcl_Interp *))
{
    AfterAssocData *assocPtr = (AfterAssocData *)clientData;
    AfterInfo *afterPtr;

    while (assocPtr->firstAfterPtr != NULL) {







|







1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
 *	After commands are removed.
 *
 *----------------------------------------------------------------------
 */

static void
AfterCleanupProc(
    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
# 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.
#
# 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)
}









|









<







1
2
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 © 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

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
}
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)
}
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)
}







<
<
<
<




|







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)
}




declare 18 {
    void TclBN_mp_exch(mp_int *a, mp_int *b)
}
declare 19 {
    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
}
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)
}




# 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)
#}
# 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)

#}
# 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)
}

# 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:







<
<
<
<
<
<
<
<









<
<
<
<
<
<
<
<
<
<
<
<
<









<
<
<
<
<
<
<
<



<
<
<
<







<
<
<
<
<









>
>
>
|
<
<
|
|
<
<
<
|
>
|
<
|
|
<
>
|
|






<
<
<
<








132
133
134
135
136
137
138








139
140
141
142
143
144
145
146
147













148
149
150
151
152
153
154
155
156








157
158
159




160
161
162
163
164
165
166





167
168
169
170
171
172
173
174
175
176
177
178
179


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)
}








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)
}













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)
}








declare 63 {
    int MP_WUR TclBN_mp_cnt_lsb(const mp_int *a)
}




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)
}






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)
}


declare 72 {
    mp_err MP_WUR 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)
}


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)
}




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
#ifndef BN_TCL_H_
#define BN_TCL_H_

#ifdef MP_NO_STDINT
#   ifdef HAVE_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 */








#   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



<
<
|
<
<
<
<
















>
>
>
>
>
>
>
>







1
2
3


4




5
6
7
8
9
10
11
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_



#include <stdint.h>




#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
#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))
/* 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))
/* MODULE_SCOPE void* TclBNRealloc( void*, size_t ); */
#define TclBNRealloc(x,s) ((void*)Tcl_Realloc((char*)(x),(size_t)(s)))
/* MODULE_SCOPE void  TclBNFree( void* ); */
#define TclBNFree(x) (Tcl_Free((char*)(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)

#ifndef MODULE_SCOPE



#   define MODULE_SCOPE extern

#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);















#ifdef __cplusplus
}
#endif

/* Rename the global symbols in libtommath to avoid linkage conflicts */

#ifndef TCL_WITH_EXTERNAL_TOMMATH







|

|

|

|






|
|
|


>
>
>
|
>





|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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) Tcl_AttemptAlloc((size_t)(s))
/* MODULE_SCOPE void* TclBNCalloc( size_t, size_t ); */
#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) Tcl_AttemptRealloc((x),(size_t)(s))
/* MODULE_SCOPE void  TclBNFree( void* ); */
#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), ((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
#   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_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
#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_ex TclBN_mp_expt_d_ex
#define mp_expt_u32 TclBN_mp_expt_u32
#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_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_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_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_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_sqr TclBN_s_mp_sqr
#define s_mp_sqr_fast TclBN_s_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







<


|
<
|


















>
>






|


















>




>


|
|
|

|







100
101
102
103
104
105
106

107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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_2d TclBN_mp_div_2d
#define mp_exch TclBN_mp_exch
#define mp_expt_d TclBN_mp_expt_n

#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_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_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_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
/* 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,
				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 */







|
<







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_n(const mp_int *a, int b, 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
/* 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 */




/* 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 */


/* 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;







|
>
>
>
>
|
>
>
>
>






|
>
>







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);
/* 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;
/* 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
    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_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 */







|







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_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
    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);
    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);
    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;








|
|




|







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 */
    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 */
    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
#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_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 \







|
|







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_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
/* 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 */


/* 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_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) */







|
|
>
>





|
>







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 */
#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 */
#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
/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * 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"








|







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 © 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
/*
 * 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.
 *
 * 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"






|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
 * tclTomMathStubLib.c --
 *
 *	Stub object that will be statically linked into extensions that want
 *	to access Tcl.
 *
 * 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"

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
/*
 * 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.
 *
 * 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
				 * 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_Trace stepTrace;	/* Used for execution traces, when tracing
				 * inside the given command */
    int 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
				 * 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;

/*





|
|
|
|














|
|


















|


|











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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 © 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. */
    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. */
    Tcl_Size length;		/* Number of non-NUL chars. in command. */
    Tcl_Trace stepTrace;	/* Used for execution traces, when tracing
				 * inside the given command */
    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[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
#define TCL_TRACE_EXEC_IN_PROGRESS	0x10
#define TCL_TRACE_EXEC_DIRECT		0x20

/*
 * Forward declarations for functions defined in this file:
 */




typedef int (Tcl_TraceTypeObjCmd)(Tcl_Interp *interp, int optionIndex,
	int 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







>
>
>
|
|







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, 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
};

/*
 * 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,
			    const char *name1, const char *name2, int flags);
static void		TraceCommandProc(ClientData 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,
			    const char *command, Tcl_Command commandInfo,
			    int objc, Tcl_Obj *const objv[]);
static void		StringTraceDeleteProc(ClientData 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 */
    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)

/*
 *----------------------------------------------------------------------
 *
 * Tcl_TraceObjCmd --
 *
 *	This function is invoked to process the "trace" Tcl command. See the







|
|
|

|


|
|
|

|
|










|















|
|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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, 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(void *clientData,
			    Tcl_Interp *interp, const char *oldName,
			    const char *newName, int flags);
static Tcl_CmdObjTraceProc2 TraceExecutionProc;
static int		StringTraceProc(void *clientData,
			    Tcl_Interp *interp, Tcl_Size level,
			    const char *command, Tcl_Command commandInfo,
			    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 {
    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)

/*
 *----------------------------------------------------------------------
 *
 * 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
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 {
	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) {
    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.
	 */







<
<
<
<
<



<
<
<


<
|
<
<
<
<
<










|







187
188
189
190
191
192
193





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. */
{





    /* Main sub commands to 'trace' */
    static const char *const traceOptions[] = {
	"add", "info", "remove",



	NULL
    };

    enum traceOptionsEnum optionIndex;






    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 (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
		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 --
 *







<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<







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;
    }








    }




























































































    return TCL_OK;









}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *
 *----------------------------------------------------------------------
 */

static int
TraceExecutionObjCmd(
    Tcl_Interp *interp,		/* Current interpreter. */
    int optionIndex,		/* Add, info or remove */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index;
    const char *name, *command;
    size_t commandLength, 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
    };

    switch ((enum traceOptions) optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	int flags = 0;
	int i, listLen, result;
	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);
	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);
	    return TCL_ERROR;




	}
	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) {
	    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);
	length = commandLength;
	if ((enum traceOptions) 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;







|
|


<

|
<
<
<






|

|


|
|












|








|

>
>
>
>






|














|
<
|







275
276
277
278
279
280
281
282
283
284
285

286
287



288
289
290
291
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. */
    enum traceOptionsEnum optionIndex,		/* Add, info or remove */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    const char *name, *command;
    Tcl_Size length;



    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 (optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	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 = 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",
		    (void *)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 (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], &length);

	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
	} 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;

	    /*
	     * First ensure the name given is valid.
	     */

	    name = TclGetString(objv[3]);
	    if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) {







|







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.
	     */

	    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
		    break;
		}
	    }
	}
	break;
    }
    case TRACE_INFO: {
	ClientData 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_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.







|



















|







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: {
	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) {
	    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
		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);
	    if (0 == numOps) {
		Tcl_DecrRefCount(elemObjPtr);
		continue;
	    }
	    eachTraceObjPtr = Tcl_NewListObj(0, NULL);
	    Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
	    Tcl_DecrRefCount(elemObjPtr);







|







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);
	    }
	    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
 *
 *----------------------------------------------------------------------
 */

static int
TraceCommandObjCmd(
    Tcl_Interp *interp,		/* Current interpreter. */
    int optionIndex,		/* Add, info or remove */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index;
    const char *name, *command;
    size_t commandLength, 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 };

    switch ((enum traceOptions) optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	int flags = 0;
	int i, listLen, result;
	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);
	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);
	    return TCL_ERROR;
	}




	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) {
	    case TRACE_CMD_RENAME:
		flags |= TCL_TRACE_RENAME;
		break;
	    case TRACE_CMD_DELETE:
		flags |= TCL_TRACE_DELETE;
		break;
	    }
	}

	command = TclGetStringFromObj(objv[5], &commandLength);
	length = commandLength;
	if ((enum traceOptions) 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;







|
|


<

|
<

|

|


|
|












|








|


>
>
>
|





|









|
<
|







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. */
    enum traceOptionsEnum optionIndex,		/* Add, info or remove */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    const char *name, *command;
    Tcl_Size length;

    static const char *const opStrings[] = { "delete", "rename", NULL };
    enum operations { TRACE_CMD_DELETE, TRACE_CMD_RENAME } index;

    switch (optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	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 = 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",
		    (void *)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 (index) {
	    case TRACE_CMD_RENAME:
		flags |= TCL_TRACE_RENAME;
		break;
	    case TRACE_CMD_DELETE:
		flags |= TCL_TRACE_DELETE;
		break;
	    }
	}

	command = TclGetStringFromObj(objv[5], &length);

	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
	} 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;

	    /*
	     * First ensure the name given is valid.
	     */

	    name = TclGetString(objv[3]);
	    if (Tcl_FindCommand(interp,name,NULL,TCL_LEAVE_ERR_MSG) == NULL) {







|







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.
	     */

	    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
		    break;
		}
	    }
	}
	break;
    }
    case TRACE_INFO: {
	ClientData 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_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);
	    if (0 == numOps) {
		Tcl_DecrRefCount(elemObjPtr);
		continue;
	    }
	    eachTraceObjPtr = Tcl_NewListObj(0, NULL);
	    Tcl_ListObjAppendElement(NULL, eachTraceObjPtr, elemObjPtr);
	    Tcl_DecrRefCount(elemObjPtr);







|


















|



















|







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: {
	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) {
	    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);
	    }
	    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
 *
 *----------------------------------------------------------------------
 */

static int
TraceVariableObjCmd(
    Tcl_Interp *interp,		/* Current interpreter. */
    int optionIndex,		/* Add, info or remove */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int index;
    const char *name, *command;
    size_t commandLength, length;
    ClientData 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
    };

    switch ((enum traceOptions) optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	int flags = 0;
	int i, listLen, result;
	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);
	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);
	    return TCL_ERROR;




	}
	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) {
	    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);
	length = commandLength;
	if ((enum traceOptions) 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]);







|
|


<

|
|
<





|

|


|
|












|








|

>
>
>
>






|














|
<
|





<
<
<
<
<







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. */
    enum traceOptionsEnum optionIndex,		/* Add, info or remove */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    const char *name, *command;
    Tcl_Size length;
    void *clientData;

    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 (optionIndex) {
    case TRACE_ADD:
    case TRACE_REMOVE: {
	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 = 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",
		    (void *)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 (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], &length);

	if (optionIndex == TRACE_ADD) {
	    CombinedTraceVarInfo *ctvarPtr = (CombinedTraceVarInfo *)Tcl_Alloc(
		    offsetof(CombinedTraceVarInfo, traceCmdInfo.command)
		    + 1 + length);

	    ctvarPtr->traceCmdInfo.flags = flags;





	    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
	     */

	    name = TclGetString(objv[3]);
	    FOREACH_VAR_TRACE(interp, name, clientData) {
		TraceVarInfo *tvarPtr = (TraceVarInfo *)clientData;

		if ((tvarPtr->length == length)
			&& ((tvarPtr->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;
		}







|
<
<
<
<







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)==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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
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
				 * 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;








|





|







903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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. */
    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
 *	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
 *	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. */
{
    Command *cmdPtr;
    CommandTrace *tracePtr;

    cmdPtr = (Command *) Tcl_FindCommand(interp, cmdName, NULL,
	    TCL_LEAVE_ERR_MSG);
    if (cmdPtr == NULL) {







|















|







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 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. */
    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) {
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
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. */
{
    CommandTrace *tracePtr;
    CommandTrace *prevPtr;
    Command *cmdPtr;
    Interp *iPtr = (Interp *)interp;
    ActiveCommandTrace *activePtr;
    int hasExecTraces = 0;







|







1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
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. */
    void *clientData)	/* Arbitrary argument to pass to proc. */
{
    CommandTrace *tracePtr;
    CommandTrace *prevPtr;
    Command *cmdPtr;
    Interp *iPtr = (Interp *)interp;
    ActiveCommandTrace *activePtr;
    int hasExecTraces = 0;
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
 *	Depends on the command associated with the trace.
 *
 *----------------------------------------------------------------------
 */

static void
TraceCommandProc(
    ClientData 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. */







|







1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
 *	Depends on the command associated with the trace.
 *
 *----------------------------------------------------------------------
 */

static void
TraceCommandProc(
    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
 */

int
TclCheckExecutionTraces(
    Tcl_Interp *interp,		/* The current interpreter. */
    const char *command,	/* Pointer to beginning of the current command
				 * string. */
    TCL_UNUSED(size_t) /*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_Obj *const objv[])	/* Pointers to Tcl_Obj of each argument. */
{
    Interp *iPtr = (Interp *) interp;
    CommandTrace *tracePtr, *lastTracePtr;
    ActiveCommandTrace active;
    int curLevel;
    int traceCode = TCL_OK;
    Tcl_InterpState state = NULL;

    if (cmdPtr->tracePtr == NULL) {
	return traceCode;
    }








|



|





|







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
 */

int
TclCheckExecutionTraces(
    Tcl_Interp *interp,		/* The current interpreter. */
    const char *command,	/* Pointer to beginning of the current command
				 * string. */
    TCL_UNUSED(Tcl_Size) /*numChars*/,
    Command *cmdPtr,		/* Points to command's Command struct. */
    int code,			/* The current result code. */
    int traceFlags,		/* Current tracing situation. */
    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;
    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
 */

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
				 * 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_Obj *const objv[])	/* Pointers to Tcl_Obj of each argument. */
{
    Interp *iPtr = (Interp *) interp;
    Trace *tracePtr, *lastTracePtr;
    ActiveInterpTrace active;
    int curLevel;
    int traceCode = TCL_OK;
    Tcl_InterpState state = NULL;

    if ((iPtr->tracePtr == NULL)
	    || (iPtr->flags & INTERP_TRACE_IN_PROGRESS)) {
	return(traceCode);
    }







|




|





|







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
 */

int
TclCheckInterpTraces(
    Tcl_Interp *interp,		/* The current interpreter. */
    const char *command,	/* Pointer to beginning of the current command
				 * string. */
    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. */
    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;
    Tcl_Size curLevel;
    int traceCode = TCL_OK;
    Tcl_InterpState state = NULL;

    if ((iPtr->tracePtr == NULL)
	    || (iPtr->flags & INTERP_TRACE_IN_PROGRESS)) {
	return(traceCode);
    }
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
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
				 * source. */
    int 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;

    /*







|

|







1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
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. */
    Tcl_Size numChars,		/* The number of characters in the command's
				 * source. */
    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
 *	May release memory.
 *
 *----------------------------------------------------------------------
 */

static void
CommandObjTraceDeleted(
    ClientData clientData)
{
    TraceCommandInfo *tcmdPtr = (TraceCommandInfo *)clientData;

    if (tcmdPtr->refCount-- <= 1) {
	Tcl_Free(tcmdPtr);
    }
}







|







1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
 *	May release memory.
 *
 *----------------------------------------------------------------------
 */

static void
CommandObjTraceDeleted(
    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
 *	interpreter-wide trace.
 *
 *----------------------------------------------------------------------
 */

static int
TraceExecutionProc(
    ClientData clientData,
    Tcl_Interp *interp,
    int level,
    const char *command,
    TCL_UNUSED(Tcl_Command),
    int objc,
    struct 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;







|

|


|
|







1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
 *	interpreter-wide trace.
 *
 *----------------------------------------------------------------------
 */

static int
TraceExecutionProc(
    void *clientData,
    Tcl_Interp *interp,
    Tcl_Size level,
    const char *command,
    TCL_UNUSED(Tcl_Command),
    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

	/*
	 * Second, create the tcl callback, if required.
	 */

	if (call) {
	    Tcl_DString cmd, sub;

	    int i, saveInterpFlags;

	    Tcl_DStringInit(&cmd);
	    Tcl_DStringAppend(&cmd, tcmdPtr->command, tcmdPtr->length);

	    /*
	     * Append command with arguments.
	     */







>
|







1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697

	/*
	 * Second, create the tcl callback, if required.
	 */

	if (call) {
	    Tcl_DString cmd, sub;
	    Tcl_Size i;
	    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
			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->flags & TCL_TRACE_ANY_EXEC) >> 2,
		   TraceExecutionProc, tcmdPtr, CommandObjTraceDeleted);
	}
    }
    if (flags & TCL_TRACE_DESTROYED) {
	if (tcmdPtr->stepTrace != NULL) {
	    Tcl_DeleteTrace(interp, tcmdPtr->stepTrace);







|







1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
			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_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
 *	Depends on the command associated with the trace.
 *
 *----------------------------------------------------------------------
 */

static char *
TraceVarProc(
    ClientData 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.
     */

    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







|














|
|
|
|















<
<
<
<
<
<
<
<
<
<
<
<
<









<
<
<







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
 *	Depends on the command associated with the trace.
 *
 *----------------------------------------------------------------------
 */

static char *
TraceVarProc(
    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 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 : ""));













		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");
		}




	    /*
	     * 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
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateObjTrace --
 *
 *	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,
 *		  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







|












|
















<
<
<
<







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
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * 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(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.
 *




 *	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
 *	applications such as profiling of run time.
 *
 *	When the trace is deleted, the 'delProc' function will be invoked,
 *	passing it the original client data.
 *
 *----------------------------------------------------------------------
 */




































Tcl_Trace
Tcl_CreateObjTrace(
    Tcl_Interp *interp,		/* Tcl interpreter */
    int level,			/* Maximum nesting level */
    int flags,			/* Flags, see above */
    Tcl_CmdObjTraceProc *proc,	/* Trace callback */
    ClientData clientData,	/* Client data for the callback */



















    Tcl_CmdObjTraceDeleteProc *delProc)
				/* Function to call when trace is deleted */
{
    Trace *tracePtr;
    Interp *iPtr = (Interp *) 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
2049
 *	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 */
    Tcl_Size level,			/* Maximum nesting level */
    int flags,			/* Flags, see above */
    Tcl_CmdObjTraceProc *proc,	/* Trace 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
 *	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;
 *	    Tcl_Interp *interp;
 *	    int level;
 *	    char *command;
 *	    int (*cmdProc)();
 *	    ClientData 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
				 * 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. */
{
    StringTraceData *data = (StringTraceData *)Tcl_Alloc(sizeof(StringTraceData));

    data->clientData = clientData;
    data->proc = proc;
    return Tcl_CreateObjTrace(interp, level, 0, StringTraceProc,
	    data, StringTraceDeleteProc);
}

/*
 *----------------------------------------------------------------------
 *
 * StringTraceProc --







|




|




















|



|





|







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
 *	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)
 *	    void *clientData;
 *	    Tcl_Interp *interp;
 *	    int level;
 *	    char *command;
 *	    int (*cmdProc)();
 *	    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. */
    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. */
    void *clientData)	/* Arbitrary value word to pass to proc. */
{
    StringTraceData *data = (StringTraceData *)Tcl_Alloc(sizeof(StringTraceData));

    data->clientData = clientData;
    data->proc = proc;
    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
 *	Whatever the string-based trace function does.
 *
 *----------------------------------------------------------------------
 */

static int
StringTraceProc(
    ClientData clientData,
    Tcl_Interp *interp,
    int level,
    const char *command,
    Tcl_Command commandInfo,
    int 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;

    /*
     * This is a bit messy because we have to emulate the old trace interface,
     * which uses strings for everything.
     */

    argv = (const char **) TclStackAlloc(interp,







|

|


|





|







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
 *	Whatever the string-based trace function does.
 *
 *----------------------------------------------------------------------
 */

static int
StringTraceProc(
    void *clientData,
    Tcl_Interp *interp,
    Tcl_Size level,
    const char *command,
    Tcl_Command commandInfo,
    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 */
    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
 *	Allocated memory is returned to the system.
 *
 *----------------------------------------------------------------------
 */

static void
StringTraceDeleteProc(
    ClientData clientData)
{
    Tcl_Free(clientData);
}

/*
 *----------------------------------------------------------------------
 *







|







2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
 *	Allocated memory is returned to the system.
 *
 *----------------------------------------------------------------------
 */

static void
StringTraceDeleteProc(
    void *clientData)
{
    Tcl_Free(clientData);
}

/*
 *----------------------------------------------------------------------
 *
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
    Var *arrayPtr,
    Tcl_Obj *name,
    int index)
{
    int code = TCL_OK;

    if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
	&& (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;







|







2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
    Var *arrayPtr,
    Tcl_Obj *name,
    int index)
{
    int code = TCL_OK;

    if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY)
	    && (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
    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;


    /*
     * If there are already similar trace functions active for the variable,
     * don't call them again.
     */

    if (TclIsVarTraceActive(varPtr)) {







>







2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
    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
		    part2 = newPart1 + offset + 1;
		    copiedName = 1;
		}
		break;
	    }
	}
    }















    /*
     * Invoke traces on the array containing the variable, if relevant.
     */

    result = NULL;
    active.nextPtr = iPtr->activeVarTracePtr;







>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
		    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;
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
		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 ? ")" : "") ));
	    if (disposeFlags & TCL_TRACE_RESULT_OBJECT) {
		TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb,
			TclGetString((Tcl_Obj *) result));
	    } else {
		TclVarErrMsg((Tcl_Interp *) iPtr, part1, part2, verb, result);
	    }
	    iPtr->flags &= ~(ERR_ALREADY_LOGGED);
	    Tcl_DiscardInterpState(state);
	} else {
	    Tcl_RestoreInterpState((Tcl_Interp *) iPtr, state);
	}
	DisposeTraceResult(disposeFlags,result);







|
|

|


|







2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
		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,
		    (element ? "(" : ""), (element ? element : ""),
		    (element ? ")" : "") ));
	    if (disposeFlags & TCL_TRACE_RESULT_OBJECT) {
		TclVarErrMsg((Tcl_Interp *) iPtr, part1, element, verb,
			TclGetString((Tcl_Obj *) result));
	    } else {
		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
    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. */
{
    VarTrace *tracePtr;
    VarTrace *prevPtr, *nextPtr;
    Var *varPtr, *arrayPtr;
    Interp *iPtr = (Interp *) interp;
    ActiveVarTrace *activePtr;
    int flagMask, allFlags = 0;







|
|







2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
    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 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
    /*
     * 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);
    for (tracePtr = (VarTrace *)Tcl_GetHashValue(hPtr), prevPtr = NULL; ;
	    prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
	if (tracePtr == NULL) {
	    goto updateFlags;







<
<
<







2802
2803
2804
2805
2806
2807
2808



2809
2810
2811
2812
2813
2814
2815
    /*
     * 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;



    flags &= flagMask;

    hPtr = Tcl_FindHashEntry(&iPtr->varTraces, (char *) varPtr);
    for (tracePtr = (VarTrace *)Tcl_GetHashValue(hPtr), prevPtr = NULL; ;
	    prevPtr = tracePtr, tracePtr = tracePtr->nextPtr) {
	if (tracePtr == NULL) {
	    goto updateFlags;
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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
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
				 * 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;







|








|
|







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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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 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;
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
 *	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
 *	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. */
{
    VarTrace *tracePtr;
    int result;

    tracePtr = (VarTrace *)Tcl_Alloc(sizeof(VarTrace));
    tracePtr->traceProc = proc;
    tracePtr->clientData = clientData;







|




















|







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
 *	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 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. */
    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
 *	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
 *	traceProc listed in tracePtr. See the manual entry for complete
 *	details on the calling sequence for proc.
 *
 *----------------------------------------------------------------------
 */

static int







|







3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
 *	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 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

    /*
     * 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);







<
<
<







3066
3067
3068
3069
3070
3071
3072



3073
3074
3075
3076
3077
3078
3079

    /*
     * 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;



    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
/*
 * 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.
 * 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.







|







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 © 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

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,
    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,
    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,
    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,







|
|
|
|
|
|






|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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, 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, 3296, 5152, 5184, 5216, 5248, 5280, 5312,
    1344, 5344, 1344, 5376, 5408, 5440, 5472, 5504, 5536, 5568, 5600, 5632,
    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
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    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, 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, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    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
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 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, 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
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,






    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, 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, 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
#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,
    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,
    1824, 1824, 1824, 1344, 13376, 13408, 13440, 1344, 13472, 13504, 1824,
    1824, 1824, 1824, 1824, 1344, 13536, 13568, 1824, 1344, 13600, 13632,
    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,
    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,
    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,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    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, 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,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 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,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    1824, 1824, 1824, 1824, 1824, 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, 4608, 4736,
    14880, 1824, 1824, 10176, 14912, 1344, 14944, 14976, 15008, 15040,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824, 1824,
    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, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 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, 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,
    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,
    1824, 1824, 1824, 1824, 1824, 1824, 1824, 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,
    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,
    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, 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,














































    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 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.







>
>
>
>
>
>
|




|
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
>
>
>
>
>
>
|


|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
|
|
>
>
|
|
<
<
<
>
>
>
>
|
<
<
<
<
>
>
>
>
|
<
<
<
<
<
>
>
>
>
>
|
|
|

|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181






182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

213

214
215




















216
217
218
219
220
221
222


223
224






















225
226



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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,
    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, 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
    ,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, 3296, 3296, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 7776, 4704, 11552, 11584, 11616, 3296,
    3296, 11648, 11680, 11712, 11744, 4736, 11776, 3296, 11808, 11840,
    11872, 3296, 3296, 1344, 11904, 11936, 6880, 11968, 12000, 12032, 12064,
    12096, 3296, 12128, 12160, 1344, 12192, 12224, 12256, 12288, 12320,
    3296, 3296, 1344, 1344, 12352, 3296, 12384, 12416, 12448, 12480, 1344,
    12512, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 12544,
    1344, 12576, 3296, 12608, 12096, 12640, 12672, 12704, 12736, 12704,
    12768, 7776, 12800, 12832, 12864, 12896, 5280, 12928, 12960, 12992,
    13024, 13056, 13088, 13120, 5280, 13152, 13184, 13216, 13248, 13280,

    13312, 3296, 13344, 13376, 13408, 13440, 13472, 13504, 13536, 13568,

    3296, 3296, 3296, 3296, 1344, 13600, 13632, 13664, 1344, 13696, 13728,
    3296, 3296, 3296, 3296, 3296, 1344, 13760, 13792, 3296, 1344, 13824,




















    13856, 13888, 1344, 13920, 13952, 3296, 4032, 13984, 14016, 3296, 3296,
    3296, 3296, 3296, 1344, 14048, 3296, 3296, 3296, 14080, 14112, 14144,
    14176, 14208, 14240, 3296, 3296, 14272, 14304, 14336, 14368, 14400,
    14432, 1344, 14464, 14496, 1344, 4608, 14528, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 14560, 14592, 14624, 14656, 14688, 14720, 3296, 3296,
    14752, 14784, 14816, 14848, 14880, 13952, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 14912, 14944, 14976, 15008, 3296, 3296, 15040,


    15072, 15104, 1344, 1344, 1344, 1344, 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, 3296, 3296, 3296, 10816,
    10816, 10816, 15136, 1344, 1344, 1344, 1344, 1344, 1344, 15168, 3296,



    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 12704, 1344, 1344,
    15200, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 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,
    15264, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 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, 14016, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 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, 4608, 4736, 15296, 1344, 4736, 15328, 15360, 1344, 15392, 15424,
    15456, 15488, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    14080, 14112, 15520, 3296, 3296, 3296, 1344, 1344, 15552, 15584, 15616,
    3296, 3296, 15648, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 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, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 4704, 3296, 12352, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 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, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,






    15744, 15776, 15808, 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, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 1344, 1344, 1344, 15840, 15872, 15904, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 704, 15936, 15968, 4928, 4928, 4928, 16000, 3296, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 8000, 4928, 16032, 4928, 16064, 16096,
    16128, 4928, 6848, 4928, 4928, 16160, 3296, 3296, 3296, 16192, 16192,
    4928, 4928, 16224, 16256, 3296, 3296, 3296, 3296, 16288, 16320, 16352,
    16384, 16416, 16448, 16480, 16512, 16544, 16576, 16608, 16640, 16672,
    16288, 16320, 16704, 16384, 16736, 16768, 16800, 16512, 16832, 16864,
    16896, 16928, 16960, 16992, 17024, 17056, 17088, 17120, 17152, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 704, 17184, 704, 17216, 17248, 17280, 3296, 3296,



    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 17312, 17344, 3296,
    3296, 3296, 3296, 3296, 3296, 17376, 17408, 5664, 17440, 17472, 3296,
    3296, 3296, 1344, 17504, 17536, 3296, 3296, 3296, 3296, 3296, 3296,




    3296, 3296, 3296, 12704, 17568, 1344, 17600, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 12704,
    17632, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 17664, 1344, 1344, 1344, 1344, 1344, 1344, 17696, 3296, 17728,





    17760, 17792, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 17824, 6880, 17856, 3296, 3296, 17888, 17920, 3296,
    3296, 3296, 3296, 3296, 3296, 17952, 17984, 18016, 18048, 18080, 18112,
    3296, 18144, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 3296, 4928,
    18176, 4928, 4928, 7968, 18208, 18240, 8000, 18272, 4928, 4928, 4928,
    4928, 18304, 3296, 18336, 18368, 18400, 18432, 18464, 3296, 3296, 3296,
    3296, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 18496, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 4928, 4928, 4928, 4928, 4928, 18528, 18560, 4928,
    4928, 4928, 18592, 4928, 4928, 18624, 18656, 18176, 4928, 18688, 4928,
    18720, 18752, 3296, 3296, 4928, 4928, 4928, 4928, 4928, 4928, 4928,
    4928, 4928, 4928, 7968, 18784, 18816, 18848, 18880, 18912, 4928, 4928,
    4928, 4928, 18944, 4928, 6848, 18976, 3296, 3296, 3296, 3296, 3296,
    3296, 3296, 3296, 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,
    19008, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344, 1344,
    1344, 1344, 1344, 1344, 1344, 1344, 1344, 19040, 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,
    15488













































































































































































#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.
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
    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,
    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, 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,







|







653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
    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, 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, 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,
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
    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,
    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, 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,
    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, 93, 125, 93, 15, 125, 125, 125, 93, 93, 93, 93,
    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,
    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, 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,
    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,







    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, 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,
    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,
    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,
    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,
    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,
    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, 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,
    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,
    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,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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, 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, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 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,
    15, 15, 15, 15, 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,
    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,
    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, 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, 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,
    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,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    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,
    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,

    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,
    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, 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,
    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,
    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,
    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,
    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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 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,
    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,
    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,
    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,
    14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 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,

    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,
    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,
    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, 15, 15, 15, 15, 15, 15, 15, 15, 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,
    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, 14, 14, 14, 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,
    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, 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, 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, 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,
    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,
    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,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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,
    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,
    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, 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, 15, 15, 15, 15, 15, 15, 15, 15, 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, 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,
    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,
    15, 15, 15, 15, 15, 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, 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,
    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, 15, 15, 15, 15, 15, 15, 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, 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,
    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,
    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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 14, 14, 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,
    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,
    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,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 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,
    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,
    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,




    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, 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, 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,
    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, 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,
    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,
    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, 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,
    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,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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,
    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, 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,
    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,
    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, 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,
    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,
    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,
    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, 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, 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,
    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,
    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,
    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,
    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, 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,
    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,
    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,
    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,

    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,

    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,
    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,
    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,























    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,
    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,
    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,
    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,
    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,
    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,
    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,
    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,
    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, 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,
    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,
    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, 0, 0, 0, 0, 0, 0, 0, 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, 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,
    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,
    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, 108, 0, 108, 108, 108, 108, 0,
    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,
    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,
    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, 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,
    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, 108, 108, 108, 108, 108, 108, 108, 108,
    108, 108, 108, 108, 108, 108, 108, 21, 21, 21, 21, 21, 21, 0, 0, 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, 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, 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, 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,
    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, 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,
    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,
    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,
    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,
    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,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,
    15, 15, 0, 15, 0, 0, 15, 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    0, 15, 15, 15, 15, 0, 15, 0, 15, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0,
    15, 0, 15, 0, 15, 0, 15, 15, 15, 0, 15, 15, 0, 15, 0, 0, 15, 0, 15,
    0, 15, 0, 15, 0, 15, 0, 15, 15, 0, 15, 0, 0, 15, 15, 15, 15, 0, 15,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15,

    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, 0, 0, 0, 0, 0, 15, 15,
    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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 7, 7, 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, 14, 14,
    14, 14, 14, 14, 14, 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, 0, 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, 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, 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, 14, 14,
    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, 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, 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, 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, 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,
    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,
    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, 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, 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:
 *







<
<
|
|
<
|
|

>
>
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>

|
|
|
|
|
|
|
|
|
>
|
<
|
>
|
|
>
>
>
>
>
|
>
>
>
>
>
>
>

<
<
<
<

|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|


|
|
|
|
|
|
|
|
|
|

|
|
|
|
|


|
|

|
|
<

|
|
<
|
|
|
|
|
|
>
|
|
|
|
|
|
|
>


>
>
>
>
>
>
>

|
<
|
|

<
<
|
<
<
|
|
<
<
|
|
|
|
|
|
|
<
|
|
|
|
|
>
|
|


|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
<


>
|
|
|
|
|

|



|
|
|
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|


|
|
|
|

|
|
|
|
|
|



|
|

|

|
|
|
<
|


|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|

|
>
|
<


|
|


|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
<
|
>
|
|
|

|

|
|
|
|
<
<

|
|
|
|

|
|
|














|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|
|
>
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|



|
|
|

|


|

|
>

<
|


|
|
|
|
|

|
|
|


|
|
|
>
|
<
|
|
|
>
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
<



















|
<

<
|
|
|
|
|
|
|

|
|
|
|
|


|


|

|
|
>
>
|
<
<


|
|
|
>
>
>
>
>
>
|
>
>
>
>
|

|
>
|
|
|
<
|
|
<
<
<
|
>
>
>
|
|
|
|
|
|
|
|
|
|

|
|
|
>
|
|
|
>
|
|
|
|
<
|
|
|
<
|
|

|
|


|
|
|
|
|
|
>
|
>
|
|
|
>
>
>







|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|
>
>
>
|
|
|
|
>
>
>
>
>
>

>
|
>

|
>
|
>
>
>
>
>
>
>
|
<
|
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
>
>
>
|
>
>
|








>
>
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>
>







|
|
<
<
|
|
|
|
|
|
|
|
|

|
|

>
|
>
>
>
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

>
|
|
<
|

>
|
|
<
|
|
|

|

|
|
|

|
|
|
|
|
<
<
<
|
|

|
|
<
|
|
>
|
|
>
>
>
|
|
|
>
>
>
|
|
|
|
>
>
|
|
>
>
>
|
|
<
<
<
<
<
>
>
>
>
>
|
|
|
|
|


|
|
|
|
|
|
|
|
>
|
|
|
|
|
|

|
<
<
<
|
|
<
|

<
|
<
<
|
<
<

<
|
|
|
|
|
|
|
|
|

>
|
|
|
|
|
|
<
|
>
>

|
|
>
>
|
|
>
>
|
|
<
>
>
>
|


|







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
    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,
    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, 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, 0, 93, 93, 93, 93, 93, 93, 93, 93,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 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,
    17, 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, 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, 93, 125, 93, 15, 125, 125, 125, 93, 93, 93, 93, 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, 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, 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, 93, 15, 93, 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, 15, 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, 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, 15, 15, 0, 15, 15, 93, 93,
    0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 15, 15, 125, 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, 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, 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, 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, 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, 93, 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, 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, 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, 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, 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, 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, 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, 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, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 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, 15, 15, 15, 15, 15, 93, 93, 93, 125, 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, 93, 93, 125, 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, 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, 93, 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, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    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, 15, 15, 15, 15, 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, 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, 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, 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, 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, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
    93, 93, 93, 120, 93, 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, 0, 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,
    93, 125, 93, 93, 93, 93, 93, 125, 93, 125, 125, 125, 125, 125, 93,
    125, 125, 15, 15, 15, 15, 15, 15, 15, 15, 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, 14, 14, 14, 14, 14, 14,
    14, 14, 3, 3, 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, 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, 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, 92, 92, 92,


    92, 92, 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, 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, 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, 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, 4, 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, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
    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, 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, 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, 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, 14, 14, 14, 14, 14, 14,
    14, 14, 14, 14, 14, 14, 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, 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, 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, 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, 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, 124, 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, 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, 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, 15, 15,
    15, 15, 15, 15, 15, 15, 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, 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, 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, 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, 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, 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,
    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, 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,
    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,
    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, 23, 24, 23, 24, 195,
    196, 197, 23, 24, 23, 24, 0, 0, 0, 0, 0, 23, 24, 0, 21, 0, 21, 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, 92, 92, 92, 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, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 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, 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, 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, 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, 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, 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, 15, 15, 15, 15, 15, 15, 15,
    15, 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, 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, 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, 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, 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,
    15, 4, 14, 14, 14, 93, 93, 93, 93, 93, 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, 15, 15, 15, 15, 15, 15,
    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,
    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, 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,
    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, 14, 14, 14, 14, 14, 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, 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, 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, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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, 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, 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, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 0,
    204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
    204, 0, 204, 204, 204, 204, 204, 204, 204, 0, 204, 204, 0, 205, 205,
    205, 205, 205, 205, 205, 205, 205, 205, 205, 0, 205, 205, 205, 205,
    205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 0, 205, 205,
    205, 205, 205, 205, 205, 0, 205, 205, 0, 0, 0, 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, 92, 92, 92, 92, 92, 92, 0, 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, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 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, 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, 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, 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,

    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, 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, 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, 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, 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, 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, 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, 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, 93, 93, 93, 93, 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, 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,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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, 93,
    15, 15, 93, 93, 15, 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, 125, 125, 125, 93,
    93, 93, 93, 125, 125, 93, 93, 3, 3, 17, 3, 3, 3, 3, 93, 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, 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, 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, 15, 15, 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, 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, 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, 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, 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, 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, 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,
    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, 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, 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, 3, 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, 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, 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, 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, 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, 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, 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, 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, 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, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 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, 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, 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, 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, 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, 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, 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,
    93, 93, 15, 125, 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, 125, 125, 93, 93, 93, 93, 93, 0, 0, 0, 125, 125, 93, 125, 93, 3,
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 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,
    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, 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,
    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, 93,
    15, 15, 15, 15, 15, 15, 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, 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, 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, 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, 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, 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, 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, 92, 92, 92, 92, 0, 92, 92, 92, 92, 92, 92,
    92, 0, 92, 92, 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, 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, 93, 93,
    93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 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, 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, 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, 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, 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, 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, 0,
    0, 0, 0, 0, 0, 0, 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, 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, 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, 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, 108,
    0, 108, 108, 108, 108, 0, 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, 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, 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, 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, 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, 108,
    108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, 108,
    21, 21, 21, 21, 21, 21, 0, 0, 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, 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, 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, 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, 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, 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, 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, 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,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 93, 93, 93, 93, 93, 93, 93, 0, 93, 93, 0, 93,
    93, 93, 93, 93, 0, 0, 0, 0, 0, 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, 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, 93, 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, 15, 15, 93, 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, 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, 15, 15, 15, 15, 15, 15, 92, 93, 93, 93, 93, 9,
    9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 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, 93, 93, 93, 93, 93, 93, 93, 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, 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, 207,
    207, 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, 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, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 0, 15, 15, 0, 15, 0, 0, 15, 0, 15, 15, 15,
    15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15, 15, 0, 15, 0, 15, 0, 0,
    0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 15, 0, 15, 0, 15, 15, 15, 0, 15,
    15, 0, 15, 0, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 0, 15, 15, 0, 15,
    0, 0, 15, 15, 15, 15, 0, 15, 15, 15, 15, 15, 15, 15, 0, 15, 15, 15,
    15, 0, 15, 15, 15, 15, 0, 15, 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, 0, 0, 0, 0, 0, 15, 15, 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, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 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, 14, 14, 14, 14, 14, 14, 14, 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, 0, 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, 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, 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, 14, 14, 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, 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, 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, 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, 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, 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, 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, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 0,
    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, 0, 0, 0, 0, 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, 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, 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, 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, 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
#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:
 *
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
    -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
};

#if TCL_UTF_MAX > 3 || TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1FFFFF) >= 0x31360)
#else
#   define UNICODE_OUT_OF_RANGE(ch) (((ch) & 0x1F0000) != 0)
#endif

/*
 * The following constants are used to determine the category of a
 * Unicode character.







|



|







1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
    -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, 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) >= 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
/*
 * tclUtf.c --
 *
 *	Routines for manipulating UTF-8 strings.
 *
 * 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.
 */

#include "tclInt.h"






|







1
2
3
4
5
6
7
8
9
10
11
12
13
/*
 * tclUtf.c --
 *
 *	Routines for manipulating UTF-8 strings.
 *
 * 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
 * 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 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))







|







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))

#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
 */

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,
    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,
#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,
#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);

/*







<
>
|
<
<

|
<
<
<
<
<
<

|










|
<
<
<
<
<
<

|







60
61
62
63
64
65
66

67
68


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,

    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,


    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,4,4,4,4,4,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,4,4,4,4,4,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
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

size_t
TclUtfCount(
    int ch)			/* The Unicode character whose size is returned. */
{
    if ((unsigned)(ch - 1) < (UNICODE_SELF - 1)) {
	return 1;
    }
    if (ch <= 0x7FF) {







|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

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
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharToUtf --
 *
 *	Store 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:
 *	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
 *	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
 *	again with ch = -1. This will produce a 3-byte UTF-8 sequence
 *	representing the high surrogate.
 *
 * Results:
 *	The return values is the number of bytes in the buffer that were
 *	consumed.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UniCharToUtf(
    int ch,			/* The Tcl_UniChar to be stored in the
				 * buffer. */

    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). */

{





    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);
	    return 2;
	}
	if (ch <= 0xFFFF) {

	    if ((ch & 0xF800) == 0xD800) {
		if (ch & 0x0400) {
		    /* Low surrogate */

		    if (((buf[0] & 0xC0) == 0x80) && ((buf[1] & 0xCF) == 0)) {
			/* Previous Tcl_UniChar was a high surrogate, so combine */
			buf[2] = (char) ((ch & 0x3F) | 0x80);
			buf[1] |= (char) (((ch >> 6) & 0x0F) | 0x80);
			return 3;
		    }
		    /* Previous Tcl_UniChar was not a high surrogate, so just output */
		} else {
		    /* High surrogate */



		    ch += 0x40;

		    /* Fill buffer with specific 3-byte (invalid) byte combination,
		       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);
		    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);
	    return 4;
	}
    } else if (ch == -1) {

	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);
	    return 2;
	}
    }

    ch = 0xFFFD;
three:
    buf[2] = (char) ((ch | 0x80) & 0xBF);
    buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
    buf[0] = (char) ((ch >> 12) | 0xE0);
    return 3;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharToUtfDString --







|
|

|
<
|
|
|
|
<

|
|
<
|


|
<







|

|
|
>
|
<
|
|
>

>
>
>
>
>






|
|



>
|


>
|

|
|





>
>
>

>

|

|
|






|
|
|
|



>
|
|
|
>
>
|
|
|
|






|
|
|







178
179
180
181
182
183
184
185
186
187
188

189
190
191
192

193
194
195

196
197
198
199

200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharToUtf --
 *
 *	Stores the given Tcl_UniChar as a sequence of UTF-8 bytes in the provided
 *	buffer. Equivalent to Plan 9 runetochar().
 *
 *	Surrogate pairs are handled as follows: When ch is a high surrogate,

 *	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.

 *
 *	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

 *	sequence representing the high surrogate.
 *
 * Results:
 *	Returns the number of bytes stored into the buffer.

 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Size
Tcl_UniCharToUtf(
    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

		 * 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) (0x80 | (0x3F & ch));
	    buf[0] = (char) (0xC0 | (ch >> 6));
	    return 2;
	}
	if (ch <= 0xFFFF) {
	    if ((flags & TCL_COMBINE) &&
		    ((ch & 0xF800) == 0xD800)) {
		if (ch & 0x0400) {
		    /* Low surrogate */
		    if (    (0x80 == (0xC0 & buf[0]))
			    && (0 == (0xCF & buf[1]))) {
			/* Previous Tcl_UniChar was a high surrogate, so combine */
			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 */
		    buf[2] = (char) ((ch << 4) & 0x30);
		    buf[1] = (char) (0x80 | (0x3F & (ch >> 2)));
		    buf[0] = (char) (0xF0 | (0x07 & (ch >> 8)));
		    return 1;
		}
	    }
	    goto three;
	}
	if (ch <= 0x10FFFF) {
	    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]))
		&& (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) (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
 *
 * 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. */

    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;

    /*
     * UTF-8 string length in bytes will be <= Unicode string length * 4.
     */

    if (uniStr == NULL) {
	return NULL;
    }
    if (uniLength == TCL_INDEX_NONE) {
	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_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;
    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) {

	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);
	p += len;
	if ((*w >= 0xD800) && (len < 3)) {
	    len = 0; /* Indication that high surrogate was found */
	}
	w++;
    }
    if (!len) {







<



|
>





|








|













>












|





|









|














>





|







303
304
305
306
307
308
309

310
311
312
313
314
315
316
317
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
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */


char *
Tcl_UniCharToUtfDString(
    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;
    Tcl_Size oldLength;

    /*
     * UTF-8 string length in bytes will be <= Unicode string length * 4.
     */

    if (uniStr == NULL) {
	return NULL;
    }
    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. */
    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;
    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 < 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 | 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
 *	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
int
Tcl_UtfToUniChar(
    const char *src,	/* The UTF-8 string. */
    int *chPtr)/* Filled with the Unicode character represented by
				 * the UTF-8 string. */
{
    int byte;








<
<
<
<
<
<
<
<
<

















|
<







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
 *	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:
 *	*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
};

Tcl_Size

Tcl_UtfToUniChar(
    const char *src,	/* The UTF-8 string. */
    int *chPtr)/* Filled with the Unicode character represented by
				 * the UTF-8 string. */
{
    int byte;

474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
	if ((unsigned)(byte-0x80) < (unsigned)0x20) {
	    *chPtr = cp1252[byte-0x80];
	} else {
	    *chPtr = byte;
	}
	return 1;
    } else if (byte < 0xE0) {
	if ((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;







|







463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
	if ((unsigned)(byte-0x80) < (unsigned)0x20) {
	    *chPtr = cp1252[byte-0x80];
	} else {
	    *chPtr = byte;
	}
	return 1;
    } else if (byte < 0xE0) {
	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
	    }
	}

	/*
	 * A three-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */
    }
    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) {







<
|







495
496
497
498
499
500
501

502
503
504
505
506
507
508
509
	    }
	}

	/*
	 * A three-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */

    } 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
	 */
    }

    *chPtr = byte;
    return 1;
}

int
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;








|







517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
	 */
    }

    *chPtr = byte;
    return 1;
}

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
	if ((unsigned)(byte-0x80) < (unsigned)0x20) {
	    *chPtr = cp1252[byte-0x80];
	} else {
	    *chPtr = byte;
	}
	return 1;
    } else if (byte < 0xE0) {
	if ((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;







|







558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
	if ((unsigned)(byte-0x80) < (unsigned)0x20) {
	    *chPtr = cp1252[byte-0x80];
	} else {
	    *chPtr = byte;
	}
	return 1;
    } else if (byte < 0xE0) {
	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
	    }
	}

	/*
	 * A three-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */
    }
    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;







<
|







590
591
592
593
594
595
596

597
598
599
600
601
602
603
604
	    }
	}

	/*
	 * A three-byte-character lead-byte not followed by two trail-bytes
	 * represents itself.
	 */

    } 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
 *
 * 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
				 * 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;
    /* 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) {
	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);
	*w++ = ch;
    }
    while ((p < endPtr) && TclUCS4Complete(p, endPtr-p)) {
	p += TclUtfToUCS4(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
				 * 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;
    /* 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) {
	length = strlen(src);
    }

    /*
     * Unicode string length in WCHARs will be <= UTF-8 string length in
     * bytes.
     */







<



|







|








|



















|


|
|















|







|








|







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
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */


int *
Tcl_UtfToUniCharDString(
    const char *src,		/* UTF-8 string to convert to Unicode. */
    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;
    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 < 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 += TclUtfToUniChar(p, &ch);
	*w++ = 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. */
    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;
    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 < 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
    endPtr = src + length;
    optPtr = endPtr - 3;
    while (p <= optPtr) {
	p += Tcl_UtfToChar16(p, &ch);
	*w++ = ch;
    }
    while (p < endPtr) {
	if (TclChar16Complete(p, endPtr-p)) {
	    p += Tcl_UtfToChar16(p, &ch);
	    *w++ = ch;
	} else {
	    *w++ = UCHAR(*p++);
	}
    }
    *w = '\0';







|







735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
    endPtr = src + length;
    optPtr = endPtr - 3;
    while (p <= optPtr) {
	p += Tcl_UtfToChar16(p, &ch);
	*w++ = ch;
    }
    while (p < endPtr) {
	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
 *---------------------------------------------------------------------------
 */

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. */
{
    return length >= complete[UCHAR(*src)];
}

/*
 *---------------------------------------------------------------------------
 *







|







772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
 *---------------------------------------------------------------------------
 */

int
Tcl_UtfCharComplete(
    const char *src,		/* String to check if first few bytes contain
				 * a complete UTF-8 character. */
    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
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

size_t
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_UniChar ch = 0;
    size_t i = 0;

    if (length == TCL_INDEX_NONE) {
	/* 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;

	/*
	 * 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.







|


|
|


|

|











|







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
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Size
Tcl_NumUtfChars(
    const char *src,	/* The UTF-8 string to measure. */
    Tcl_Size length)	/* The length of the string in bytes, or
			 * negative value for strlen(src). */
{
    Tcl_UniChar ch = 0;
    Tcl_Size i = 0;

    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 - 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
	    }
	    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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    }
	    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

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);

	if (find == ch) {
	    return src;
	}
	if (*src == '\0') {
	    return NULL;
	}







|







924
925
926
927
928
929
930
931
932
933
934
935
936
937
938

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 = 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
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);

	if (find == ch) {
	    last = src;
	}
	if (*src == '\0') {
	    break;
	}







|







963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
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 = 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
 *---------------------------------------------------------------------------
 */

const char *
Tcl_UtfNext(
    const char *src)		/* The current location in the string. */
{
    size_t left;
    const char *next;

    if (((*src) & 0xC0) == 0x80) {




	if ((((*++src) & 0xC0) == 0x80) && (((*++src) & 0xC0) == 0x80)) {
	    ++src;
	}
	return src;
    }

    left = totalBytes[UCHAR(*src)];







|



>
>
>
>







1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
 *---------------------------------------------------------------------------
 */

const char *
Tcl_UtfNext(
    const char *src)		/* The current location in the string. */
{
    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
		/*
		 * 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])) {
		/*
		 * 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







|







1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
		/*
		 * 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 >= 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
	     * 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);

    /*
     * We've seen TCL_UTF_MAX 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
     * far as we can.
     */
#if TCL_UTF_MAX > 3
    return fallback;
#else
    return src - TCL_UTF_MAX;
#endif
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UniCharAtIndex --
 *







|


|

|
<

<

<
<
<







1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156

1157

1158



1159
1160
1161
1162
1163
1164
1165
	     * and exit this loop before we run past the start of the string.
	     */
	    return fallback;
	}

	/* Continue the search backwards... */
	look--;
    } while (trailBytesSeen < 4);

    /*
     * 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.

     */

    return fallback;



}

/*
 *---------------------------------------------------------------------------
 *
 * 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
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UniCharAtIndex(
    const char *src,	/* The UTF-8 string to dereference. */
    size_t index)		/* The position of the desired character. */
{
    Tcl_UniChar ch = 0;
    int i = 0;

    if (index == TCL_INDEX_NONE) {
	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);
    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
 *	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_UniChar ch = 0;
#if TCL_UTF_MAX <= 3












    size_t len = 0;
#endif

    if (index != TCL_INDEX_NONE) {
	while (index--) {
#if TCL_UTF_MAX <= 3
	    src += (len = TclUtfToUniChar(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);
    }
#endif
    }
    return src;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfBackslash --
 *
 *	Figure out how to handle a backslash sequence.
 *







|




|






<
<
<
<
<
<
|









|
<
<













|


|
>
>
>
>
>
>
>
>
>
>
>
>
|
<

|

<
|
<
<
<

<
|
|
|
|
<



|







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
 *
 *---------------------------------------------------------------------------
 */

int
Tcl_UniCharAtIndex(
    const char *src,	/* The UTF-8 string to dereference. */
    Tcl_Size index)	/* The position of the desired character. */
{
    Tcl_UniChar ch = 0;
    int i = 0;

    if (index < 0) {
	return -1;
    }
    while (index--) {
	i = TclUtfToUniChar(src, &ch);
	src += i;
    }






    TclUtfToUniChar(src, &i);
    return i;
}

/*
 *---------------------------------------------------------------------------
 *
 * Tcl_UtfAtIndex --
 *
 *	Returns a pointer to the specified character (not byte) position in
 *	the UTF-8 string.


 *
 * Results:
 *	As above.
 *
 * Side effects:
 *	None.
 *
 *---------------------------------------------------------------------------
 */

const char *
Tcl_UtfAtIndex(
    const char *src,	/* The UTF-8 string. */
    Tcl_Size index)	/* The position of the desired character. */
{
    Tcl_UniChar ch = 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;


    if (index > 0) {
	while (index--) {

	    src += (len = Tcl_UtfToChar16(src, &ch));



	}

	if ((ch >= 0xD800) && (len < 3)) {
	    /* Index points at character following high Surrogate */
	    src += Tcl_UtfToChar16(src, &ch);
	}

    }
    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
 *	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_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

    size_t numRead, result;

    result = TclParseBackslash(src, LINE_LENGTH, &numRead, dst);
    if (numRead == LINE_LENGTH) {
	/*
	 * We ate a whole line. Pay the price of a strlen()
	 */








|









>
|







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
 *	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.
 *
 *---------------------------------------------------------------------------
 */

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;
    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
 *
 * Side effects:
 *	Writes a terminating null after the last converted character.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UtfToUpper(
    char *str)			/* String to convert in place. */
{
    int ch, upChar;
    char *src, *dst;
    size_t len;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	len = TclUtfToUCS4(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)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(upChar, dst);
	}
	src += len;
    }







|





|







|








|







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
 *
 * Side effects:
 *	Writes a terminating null after the last converted character.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_UtfToUpper(
    char *str)			/* String to convert in place. */
{
    int ch, upChar;
    char *src, *dst;
    Tcl_Size len;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	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)) {
	    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
 *
 * Side effects:
 *	Writes a terminating null after the last converted character.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UtfToLower(
    char *str)			/* String to convert in place. */
{
    int ch, lowChar;
    char *src, *dst;
    size_t len;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	len = TclUtfToUCS4(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)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(lowChar, dst);
	}
	src += len;
    }







|





|







|








|







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
 *
 * Side effects:
 *	Writes a terminating null after the last converted character.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_UtfToLower(
    char *str)			/* String to convert in place. */
{
    int ch, lowChar;
    char *src, *dst;
    Tcl_Size len;

    /*
     * Iterate over the string until we hit the terminating null.
     */

    src = dst = str;
    while (*src) {
	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)) {
	    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
 *
 * Side effects:
 *	Writes a terminating null after the last converted character.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UtfToTitle(
    char *str)			/* String to convert in place. */
{
    int ch, titleChar, lowChar;
    char *src, *dst;
    size_t 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);
	titleChar = Tcl_UniCharToTitle(ch);

	if ((len < TclUtfCount(titleChar)) || ((titleChar & ~0x7FF) == 0xD800)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(titleChar, dst);
	}
	src += len;
    }
    while (*src) {
	len = TclUtfToUCS4(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)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(lowChar, dst);
	}
	src += len;
    }







|





|









|


|








|






|







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
 *
 * Side effects:
 *	Writes a terminating null after the last converted character.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_UtfToTitle(
    char *str)			/* String to convert in place. */
{
    int ch, titleChar, lowChar;
    char *src, *dst;
    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 = TclUtfToUniChar(src, &ch);
	titleChar = Tcl_UniCharToTitle(ch);

	if (len < TclUtfCount(titleChar)) {
	    memmove(dst, src, len);
	    dst += len;
	} else {
	    dst += Tcl_UniCharToUtf(titleChar, dst);
	}
	src += len;
    }
    while (*src) {
	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)) {
	    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclpUtfNcmp2(
    const char *cs,		/* UTF string to compare to ct. */
    const char *ct,		/* UTF string cs is compared to. */
    size_t numBytes)	/* Number of *bytes* to compare. */
{


    /*
     * 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;







|
|


>
>







1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclpUtfNcmp2(
    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
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * Results:
 *	Return <0 if cs < ct, 0 if cs == ct, or >0 if cs > ct.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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. */
{
    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
 *	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
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. */
{
    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);
	    }
	}
    }







|
|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|



















<
<
<
<
<
<
<
<
<
<











|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|












<
<
<
<
<
<
<
<
<
<







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
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UtfNcmp --
 *
 *	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 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) {










	    return (ch1 - ch2);
	}
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_UtfNcasecmp --
 *
 *	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 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) {










	    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
{
    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);
}









<
<
<
<
<
<
<
<
<
<







1708
1709
1710
1711
1712
1713
1714










1715
1716
1717
1718
1719
1720
1721
{
    Tcl_UniChar ch1 = 0, ch2 = 0;

    while (*cs && *ct) {
	cs += TclUtfToUniChar(cs, &ch1);
	ct += TclUtfToUniChar(ct, &ch2);
	if (ch1 != ch2) {










	    return ch1 - ch2;
	}
    }
    return UCHAR(*cs) - UCHAR(*ct);
}


1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
{
    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;
	    }
	}
    }







<
<
<
<
<
<
<
<
<
<







1744
1745
1746
1747
1748
1749
1750










1751
1752
1753
1754
1755
1756
1757
{
    Tcl_UniChar ch1 = 0, ch2 = 0;

    while (*cs && *ct) {
	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;
	    }
	}
    }
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
	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.
 *







|







1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
	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
    /* Clear away extension bits, if any */
    return ch & 0x1FFFFF;
}

/*
 *----------------------------------------------------------------------
 *






























 * TclUniCharLen --
 *
 *	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. */
{
    size_t 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.
 *
 * 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. */
{
#ifdef WORDS_BIGENDIAN
    /*
     * We are definitely on a big-endian machine; memcmp() is safe
     */

    return memcmp(ucs, uct, numChars*sizeof(Tcl_UniChar));

#else /* !WORDS_BIGENDIAN */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|













|
|
|

|













|
|














|

|







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
    /* 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;
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_UniCharLen(
    const int *uniStr)	/* Unicode string to find length of. */
{
    Tcl_Size len = 0;

    while (*uniStr != '\0') {
	len++;
	uniStr++;
    }
    return len;
}

/*
 *----------------------------------------------------------------------
 *
 * TclUniCharNcmp --
 *
 *	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 chars to compare. */
{
#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
}

/*
 *----------------------------------------------------------------------
 *
 * TclUniCharNcasecmp --
 *
 *	Compare at most numChars unichars of string ucs to string uct case
 *	insensitive. Both ucs and uct are assumed to be at least numChars
 *	unichars 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. */
{
    for ( ; numChars != 0; numChars--, ucs++, uct++) {
	if (*ucs != *uct) {
	    Tcl_UniChar lcs = Tcl_UniCharToLower(*ucs);
	    Tcl_UniChar lct = Tcl_UniCharToLower(*uct);

	    if (lcs != lct) {







|

|














|







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
}

/*
 *----------------------------------------------------------------------
 *
 * TclUniCharNcasecmp --
 *
 *	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
 *	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 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
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 1;
	}
	if ((ch >= 0xF0000) && ((ch & 0xFFFF) <= 0xFFFD)) {
	    return 1;
	}
	return 0;
    }
    return ((CONTROL_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *







|
<
<
<
<
<
<







2074
2075
2076
2077
2078
2079
2080
2081






2082
2083
2084
2085
2086
2087
2088
int
Tcl_UniCharIsControl(
    int ch)			/* Unicode character to test. */
{
    if (UNICODE_OUT_OF_RANGE(ch)) {
	/* Clear away extension bits, if any */
	ch &= 0x1FFFFF;
	return ((ch == 0xE0001) || ((unsigned)(ch - 0xE0020) <= 0x5F));






    }
    return ((CONTROL_BITS >> GetCategory(ch)) & 1);
}

/*
 *----------------------------------------------------------------------
 *
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
 *
 *----------------------------------------------------------------------
 */

int
TclUniCharMatch(
    const Tcl_UniChar *string,	/* Unicode String. */
    size_t strLen,			/* Length of String */
    const Tcl_UniChar *pattern,	/* Pattern, which may contain special
				 * characters. */
    size_t 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;







|


|







2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
 *
 *----------------------------------------------------------------------
 */

int
TclUniCharMatch(
    const Tcl_UniChar *string,	/* Unicode String. */
    Tcl_Size strLen,		/* Length of String */
    const Tcl_UniChar *pattern,	/* Pattern, which may contain special
				 * characters. */
    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
	    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:
 */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2682
2683
2684
2685
2686
2687
2688




















































2689
2690
2691
2692
2693
2694
2695
	    return 0;
	}
	string++;
	pattern++;
    }
}





















































/*
 * 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
/*
 * 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.
 *
 * 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 "tclParse.h"
#include "tclStringTrim.h"
#include "tclTomMath.h"
#include <math.h>

/*






|
|
|





>







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 © 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
#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 int		GetEndOffsetFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    size_t 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);
static int		FindElement(Tcl_Interp *interp, const char *string,
			    int stringLength, const char *typeStr,
			    const char *typeCode, const char **elementPtr,
			    const char **nextPtr, size_t *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
 * 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 */

};








/*
 *	*	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.







|
|

|


|

|

|






|










|
>


>
>
>
>
>
>
>







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#define CONVERT_ANY	16

/*
 * Prototypes for functions defined later in this file.
 */

static void		ClearHash(Tcl_HashTable *tablePtr);
static void		FreeProcessGlobalValue(void *clientData);
static void		FreeThreadHash(void *clientData);
static int		GetEndOffsetFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    Tcl_WideInt endValue, Tcl_WideInt *indexPtr);
static Tcl_HashTable *	GetThreadHash(Tcl_ThreadDataKey *keyPtr);
static int		GetWideForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr,
			    Tcl_WideInt endValue, Tcl_WideInt *widePtr);
static int		FindElement(Tcl_Interp *interp, const char *string,
			    Tcl_Size stringLength, const char *typeStr,
			    const char *typeCode, const char **elementPtr,
			    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 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 */
    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.
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
/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * 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
TclMaxListLength(
    const char *bytes,
    size_t numBytes,
    const char **endPtr)
{
    size_t count = 0;

    if ((numBytes == 0) || ((numBytes == TCL_INDEX_NONE) && (*bytes == '\0'))) {
	/* Empty string case - quick exit */
	goto done;
    }

    /*







|
|
|
|












|


|


|







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 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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclMaxListLength(
    const char *bytes,
    Tcl_Size numBytes,
    const char **endPtr)
{
    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
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. */
    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
				 * 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. */







|





|







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). */
    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). */
    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
    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. */
    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
				 * 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. */







|






|







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). */
    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). */
    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
    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. */
    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
				 * 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. */
    int inQuotes = 0;
    int size = 0;
    size_t 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).







|









|











|

|
|







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). */
    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). */
    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. */
    Tcl_Size openBraces = 0;	/* Brace nesting level during parse. */
    int inQuotes = 0;
    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
			    && (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);
		}
		return TCL_ERROR;
	    }
	    break;

	    /*
	     * Backslash: skip over everything up to the end of the backslash







|







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",
			    (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
			    && (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);
		}
		return TCL_ERROR;
	    }
	    break;

	default:
	    if (TclIsSpaceProcM(*p)) {







|







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",
			    (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

    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);
	    }
	    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);
	    }
	    return TCL_ERROR;
	}
	size = (p - elemStart);
    }

  done:







|







|







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",
			(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",
			(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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
TclCopyAndCollapse(
    size_t count,			/* Number of byte to copy from src. */
    const char *src,		/* Copy from here... */
    char *dst)			/* ... to here. */
{
    size_t newCount = 0;

    while (count > 0) {
	char c = *src;

	if (c == '\\') {

	    size_t numRead;
	    size_t backslashCount = TclParseBackslash(src, count, &numRead, dst);


	    dst += backslashCount;
	    newCount += backslashCount;
	    src += numRead;
	    count -= numRead;
	} else {
	    *dst = c;
	    dst++;







|

|



|





>
|
|

>







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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclCopyAndCollapse(
    Tcl_Size count,		/* Number of byte to copy from src. */
    const char *src,		/* Copy from here... */
    char *dst)			/* ... to here. */
{
    Tcl_Size newCount = 0;

    while (count > 0) {
	char c = *src;

	if (c == '\\') {
	    char buf[4] = "";
	    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
 *
 * Side effects:
 *	Memory is allocated.
 *
 *----------------------------------------------------------------------
 */


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
				 * 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 length, size, i, result;
    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;
    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;







>





|






>
|
<









|







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. */
    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;
    Tcl_Size length, size, i, 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, 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
	}
	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);
	    }
	    return TCL_ERROR;
	}
	argv[i] = p;
	if (literal) {
	    memcpy(p, element, elSize);
	    p += elSize;







|







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",
			(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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
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);
}

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 * 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_ScanCountedElement(
    const char *src,		/* String to convert to Tcl list element. */
    size_t length,		/* Number of bytes in src, or -1. */
    int *flagPtr)		/* Where to store information to guide
				 * Tcl_ConvertElement. */
{
    char flags = CONVERT_ANY;
    int 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
 *	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







|





|










|
|













|


|




|













|







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.
 *
 *----------------------------------------------------------------------
 */

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, 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 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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_ScanCountedElement(
    const char *src,		/* String to convert to Tcl list element. */
    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;
    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 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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
TclScanElement(
    const char *src,		/* String to convert to Tcl list element. */
    size_t length,		/* Number of bytes in src, or -1. */
    char *flagPtr)		/* Where to store information to guide
				 * Tcl_ConvertElement. */
{
    const char *p = src;
    int 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
				 * formatted element, assuming we use escape
				 * sequences in formatting. */
    size_t 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 */








|


|




|




|


|







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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclScanElement(
    const char *src,		/* String to convert to Tcl list element. */
    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;
    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. */
    Tcl_Size extra = 0;		/* Count of number of extra bytes needed for
				 * formatted element, assuming we use escape
				 * sequences in formatting. */
    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
	    nestingLevel++;
	    break;
	case '}':	/* TYPE_BRACE */
#if COMPAT
	    braceCount++;
#endif /* COMPAT */
	    extra++;				/* Escape '}' => '\}' */
	    nestingLevel--;
	    if (nestingLevel < 0) {
		/*
		 * Unbalanced braces!  Cannot format with brace quoting.
		 */

		requireEscape = 1;
	    }
	    break;







<
|







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 '}' => '\}' */

	    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
#if COMPAT
		preferBrace = 1;
#endif
	    }
	    break;
	}
      }
	length -= (length+1 > 1);
	p++;
    }

  endOfString:
    if (nestingLevel != 0) {
	/*
	 * Unbalanced braces!  Cannot format with brace quoting.
	 */

	requireEscape = 1;
    }








|




|







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 > 0);
	p++;
    }

  endOfString:
    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

#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.
	     */

	    bytesNeeded += (extra - braceCount);
	    /* Make room to escape leading #, if needed. */
	    if ((*src == '#') && !(*flagPtr & TCL_DONT_QUOTE_HASH)) {
		bytesNeeded++;
	    }







|







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 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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
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);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ConvertCountedElement --
 *







|





|







1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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, 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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
Tcl_ConvertCountedElement(
    const char *src,	/* Source information for list element. */
    size_t length,		/* Number of bytes in src, or -1. */
    char *dst,			/* Place to put list-ified element. */
    int flags)			/* Flags produced by Tcl_ScanElement. */
{
    size_t numBytes = TclConvertElement(src, length, dst, flags);
    dst[numBytes] = '\0';
    return numBytes;
}

/*
 *----------------------------------------------------------------------
 *







|


|



|







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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
Tcl_ConvertCountedElement(
    const char *src,	/* Source information for list element. */
    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. */
{
    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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
TclConvertElement(
    const char *src,	/* Source information for list element. */
    size_t length,		/* Number of bytes in src, or -1. */
    char *dst,			/* Place to put list-ified element. */
    int flags)			/* Flags produced by Tcl_ScanElement. */
{
    int conversion = flags & CONVERT_MASK;
    char *p = dst;

    /*







|


|







1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclConvertElement(
    const char *src,	/* Source information for list element. */
    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

    if ((*src == '#') && !(flags & TCL_DONT_QUOTE_HASH)) {
	if (conversion == CONVERT_ESCAPE) {
	    p[0] = '\\';
	    p[1] = '#';
	    p += 2;
	    src++;
	    length -= (length+1 > 1);
	} else {
	    conversion = CONVERT_BRACE;
	}
    }

    /*
     * No escape or quoting needed.  Copy the literal string value.







|







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 > 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
	    }
	} else {
	    memcpy(p, src, length);
	    p += length;
	}
	*p = '}';
	p++;
	return (size_t)(p - dst);
    }

    /* conversion == CONVERT_ESCAPE or CONVERT_MASK */

    /*
     * Formatted string is original string converted to escape sequences.
     */

    for ( ; length; src++, length -= (length+1 > 1)) {
	switch (*src) {
	case ']':
	case '[':
	case '$':
	case ';':
	case ' ':
	case '\\':







|








|







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 (p - dst);
    }

    /* conversion == CONVERT_ESCAPE or CONVERT_MASK */

    /*
     * Formatted string is original string converted to escape sequences.
     */

    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
	    *p = '\\';
	    p++;
	    *p = 'v';
	    p++;
	    continue;
	case '\0':
	    if (length == TCL_INDEX_NONE) {
		return (size_t)(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);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Merge --
 *







|















|







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 (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 (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
 *	None.
 *
 *----------------------------------------------------------------------
 */

char *
Tcl_Merge(
    int 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;
    size_t bytesNeeded = 0;
    char *result, *dst;

    /*
     * Handle empty list case first, so logic of the general case can be
     * simpler.
     */


    if (argc == 0) {


	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 += 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 = ' ';
	dst++;
    }
    dst[-1] = 0;

    if (flagPtr != localFlags) {
	Tcl_Free(flagPtr);







|




|








>
|
>
>
















|











|







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(
    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;
    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) {
	    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], 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], 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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
TclTrimRight(
    const char *bytes,	/* String to be trimmed... */
    size_t 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 */
			/* 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;

	pp = TclUtfPrev(p, bytes);
	do {
	    pp += pInc;
 	    pInc = TclUtfToUCS4(pp, &ch1);
	} while (pp + pInc < p);

	/*
	 * Inner loop: scan trim string for match to current character.
	 */

	do {
	    size_t qInc = TclUtfToUCS4(q, &ch2);

	    if (ch1 == ch2) {
		break;
	    }

	    q += qInc;
	    bytesLeft -= qInc;
	} while (bytesLeft);

	if (bytesLeft == 0) {
	    /*
	     * No match; trim task done; *p is last non-trimmed char.
	     */








|


|



|

















|

|


|







|





|
|







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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclTrimRight(
    const char *bytes,	/* String to be trimmed... */
    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... */
    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;
	Tcl_Size pInc = 0, bytesLeft = numTrim;

	pp = Tcl_UtfPrev(p, bytes);
	do {
	    pp += pInc;
 	    pInc = TclUtfToUniChar(pp, &ch1);
	} while (pp + pInc < p);

	/*
	 * Inner loop: scan trim string for match to current character.
	 */

	do {
	    pInc = TclUtfToUniChar(q, &ch2);

	    if (ch1 == ch2) {
		break;
	    }

	    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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
TclTrimLeft(
    const char *bytes,	/* String to be trimmed... */
    size_t 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 */
			/* Calls to TclUtfToUniChar() in this routine
			 * rely on (trim[numTrim] == '\0'). */
{
    const char *p = bytes;
	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);
	const char *q = trim;
	size_t bytesLeft = numTrim;

	/*
	 * Inner loop: scan trim string for match to current character.
	 */

	do {
	    size_t qInc = TclUtfToUCS4(q, &ch2);

	    if (ch1 == ch2) {
		break;
	    }

	    q += qInc;
	    bytesLeft -= qInc;







|


|



|




|











|

|






|







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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclTrimLeft(
    const char *bytes,	/* String to be trimmed... */
    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... */
    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;

    /* Empty strings -> nothing to do */
    if ((numBytes == 0) || (numTrim == 0)) {
	return 0;
    }

    /*
     * Outer loop: iterate over string to be trimmed.
     */

    do {
	Tcl_Size pInc = TclUtfToUniChar(p, &ch1);
	const char *q = trim;
	Tcl_Size bytesLeft = numTrim;

	/*
	 * Inner loop: scan trim string for match to current character.
	 */

	do {
	    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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

size_t
TclTrim(
    const char *bytes,	/* String to be trimmed... */
    size_t 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 */
			/* Calls in this routine
			 * rely on (trim[numTrim] == '\0'). */
    size_t *trimRightPtr)	/* Offset from the end of the string. */
{
    size_t 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);
	    numBytes -= (bytes - first);

	    if (numBytes > 0) {
		/* When bytes is NUL-terminated, returns
		 * 0 <= trimRight <= numBytes */
		trimRight = TclTrimRight(bytes, numBytes, trim, numTrim);
	    }







|


|



|


|

|













|







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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclTrim(
    const char *bytes,	/* String to be trimmed... */
    Tcl_Size numBytes,	/* ...and its length in bytes */
			/* Calls in this routine
			 * rely on (bytes[numBytes] == '\0'). */
    const char *trim,	/* String of trim characters... */
    Tcl_Size numTrim,	/* ...and its length in bytes */
			/* Calls in this routine
			 * rely on (trim[numTrim] == '\0'). */
    Tcl_Size *trimRightPtr)	/* Offset from the end of the string. */
{
    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 += 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
 */

/* 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. */
    const char *const *argv)	/* Array of strings to concatenate. */
{
    int i;
    size_t 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]);



    }

    /*
     * All element bytes + (argc - 1) spaces + 1 terminating NULL.
     */









    result = (char *)Tcl_Alloc(bytesNeeded + argc);

    for (p = result, i = 0;  i < argc;  i++) {
	size_t 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,







|


<
|


















>
>
>





>
>
>
>
>
>
>
>




|







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(
    Tcl_Size argc,			/* Number of strings to concatenate. */
    const char *const *argv)	/* Array of strings to concatenate. */
{

    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++) {
	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
 *	A new object is created.
 *
 *----------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_ConcatObj(
    int objc,			/* Number of objects to concatenate. */
    Tcl_Obj *const objv[])	/* Array of objects to concatenate. */
{
    int i, needSpace = 0;
    size_t 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;

	objPtr = objv[i];
	if (TclListObjIsCanonical(objPtr)) {

	    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)) {

		continue;
	    }
	    if (resPtr) {







		if (TCL_OK != Tcl_ListObjAppendList(NULL, resPtr, objPtr)) {
		    /* Abandon ship! */
		    Tcl_DecrRefCount(resPtr);

		    goto slow;
		}

	    } 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.
     */

    for (i = 0;  i < objc;  i++) {
	element = TclGetStringFromObj(objv[i], &elemLength);



	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;

	element = TclGetStringFromObj(objv[i], &elemLength);

	/* Trim away the leading/trailing whitespace. */
	triml = TclTrim(element, elemLength, CONCAT_TRIM_SET,
		CONCAT_WS_SIZE, &trimr);
	element += triml;







|


|
|










|


|
>











|
>



>
>
>
>
>
>
>
|


>


>















|




>
>
>














|







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(
    Tcl_Size objc,		/* Number of objects to concatenate. */
    Tcl_Obj *const objv[])	/* Array of objects to concatenate. */
{
    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++) {
	Tcl_Size length;

	objPtr = objv[i];
	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) &&
		    !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
			!= 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 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++) {
	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
	 */

	if (p == '*') {
	    /*
	     * Skip all successive *'s in the 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);
		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);
			    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);
			    if (ch2 == ch1) {
				break;
			    }
			    str += charLen;
			}
		    }
		}
		if (Tcl_StringCaseMatch(str, pattern, nocase)) {
		    return 1;
		}
		if (*str == '\0') {
		    return 0;
		}
		str += TclUtfToUCS4(str, &ch1);
	    }
	}

	/*
	 * Check for a "?" as the next pattern character. It matches any
	 * single character.
	 */

	if (p == '?') {
	    pattern++;
	    str += TclUtfToUCS4(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);
		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);
		    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);
			if (nocase) {
			    endChar = Tcl_UniCharToLower(endChar);
			}
		    }
		    if (((startChar <= ch1) && (ch1 <= endChar))
			    || ((endChar <= ch1) && (ch1 <= startChar))) {
			/*







|













|















|













|













|










|


















|













|














|







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) == '*');
	    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 {
		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 = 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 = TclUtfToUniChar(str, &ch1);
			    if (ch2 == ch1) {
				break;
			    }
			    str += charLen;
			}
		    }
		}
		if (Tcl_StringCaseMatch(str, pattern, nocase)) {
		    return 1;
		}
		if (*str == '\0') {
		    return 0;
		}
		str += TclUtfToUniChar(str, &ch1);
	    }
	}

	/*
	 * Check for a "?" as the next pattern character. It matches any
	 * single character.
	 */

	if (p == '?') {
	    pattern++;
	    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 += 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 += 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 += 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
	}

	/*
	 * There's no special character. Just make sure that the next bytes of
	 * each string match.
	 */

	str += TclUtfToUCS4(str, &ch1);
	pattern += TclUtfToUCS4(pattern, &ch2);
	if (nocase) {
	    if (Tcl_UniCharToLower(ch1) != Tcl_UniCharToLower(ch2)) {
		return 0;
	    }
	} else if (ch1 != ch2) {
	    return 0;
	}







|
|







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 += 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
 *
 *----------------------------------------------------------------------
 */

int
TclByteArrayMatch(
    const unsigned char *string,/* String. */
    size_t strLen,			/* Length of String */
    const unsigned char *pattern,
				/* Pattern, which may contain special
				 * characters. */
    size_t ptnLen,			/* Length of Pattern */
    TCL_UNUSED(int) /*flags*/)
{
    const unsigned char *stringEnd, *patternEnd;
    unsigned char p;

    stringEnd = string + strLen;
    patternEnd = pattern + ptnLen;







|



|







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. */
    Tcl_Size strLen,			/* Length of String */
    const unsigned char *pattern,
				/* Pattern, which may contain special
				 * characters. */
    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

		if ((p != '[') && (p != '?') && (p != '\\')) {
		    while ((string < stringEnd) && (p != *string)) {
			string++;
		    }
		}
		if (TclByteArrayMatch(string, stringEnd - string,
				pattern, patternEnd - pattern, 0)) {
		    return 1;
		}
		if (string == stringEnd) {
		    return 0;
		}
		string++;
	    }







|







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)) {
		    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
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;

    /*
     * 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)) {
	Tcl_UniChar *udata, *uptn;

	udata = TclGetUnicodeFromObj(strObj, &length);
	uptn  = TclGetUnicodeFromObj(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);
	match = TclByteArrayMatch(data, length, ptn, plen, 0);
    } else {
	match = Tcl_StringCaseMatch(TclGetString(strObj),
		TclGetString(ptnObj), flags);
    }
    return match;
}







|








|


|
|





|
|







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;
    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 (TclHasInternalRep(strObj, &tclStringType) || (strObj->typePtr == NULL)) {
	Tcl_UniChar *udata, *uptn;

	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 = 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;
}
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
 */

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. */
{
    size_t newSize;

    if (length == TCL_INDEX_NONE) {
	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
     * room to grow before we have to allocate again.
     */

    if (newSize >= dsPtr->spaceAvl) {
	dsPtr->spaceAvl = newSize * 2;
	if (dsPtr->string == dsPtr->staticSpace) {
	    char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);

	    memcpy(newString, dsPtr->string, dsPtr->length);
	    dsPtr->string = newString;
	} else {
	    size_t index = TCL_INDEX_NONE;

	    /* See [16896d49fd] */
	    if (bytes >= dsPtr->string
		    && bytes <= dsPtr->string + dsPtr->length) {

		index = bytes - dsPtr->string;
	    }

	    dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, dsPtr->spaceAvl);

	    if (index != TCL_INDEX_NONE) {
		bytes = dsPtr->string + index;
	    }
	}
    }

    /*
     * Copy the new string into the buffer at the end of the old one.
     */







|



|

|


>
>
>
>
>
>
>
|

<
<
<
<
<

|
<

|
|



|




>
|

<
|
|
|
|







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. */
    Tcl_Size length)		/* Number of bytes from "bytes" to append. If
				 * TCL_INDEX_NONE, then append all of bytes, up to null
				 * at end. */
{
    Tcl_Size newSize;

    if (length < 0) {
	length = strlen(bytes);
    }

    if (length > (TCL_SIZE_MAX - dsPtr->length - 1)) {
	Tcl_Panic("max size for a Tcl value (%" TCL_SIZE_MODIFIER
		  "d bytes) exceeded",
		  TCL_SIZE_MAX);
	return NULL; /* NOTREACHED */
    }
    newSize = length + dsPtr->length + 1;







    if (newSize > dsPtr->spaceAvl) {

	if (dsPtr->string == dsPtr->staticSpace) {
	    char *newString;
	    newString = (char *) TclAllocEx(newSize, &dsPtr->spaceAvl);
	    memcpy(newString, dsPtr->string, dsPtr->length);
	    dsPtr->string = newString;
	} else {
	    Tcl_Size offset = -1;

	    /* See [16896d49fd] */
	    if (bytes >= dsPtr->string
		    && bytes <= dsPtr->string + dsPtr->length) {
		/* Source string is within this DString. Note offset */
		offset = bytes - dsPtr->string;
	    }

	    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
 */

char *
TclDStringAppendObj(
    Tcl_DString *dsPtr,
    Tcl_Obj *objPtr)
{
    size_t length;
    const char *bytes = TclGetStringFromObj(objPtr, &length);

    return Tcl_DStringAppend(dsPtr, bytes, length);
}

char *
TclDStringAppendDString(







|







2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
 */

char *
TclDStringAppendObj(
    Tcl_DString *dsPtr,
    Tcl_Obj *objPtr)
{
    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
    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;

    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.
	 */







|







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;
    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

	/* 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);
    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) {
	dsPtr->spaceAvl = newSize * 2;
	if (dsPtr->string == dsPtr->staticSpace) {
	    char *newString = (char *)Tcl_Alloc(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) {

		offset = element - dsPtr->string;
	    }

	    dsPtr->string = (char *)Tcl_Realloc(dsPtr->string, 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->string[dsPtr->length] = '\0';
    return dsPtr->string;
}

/*
 *----------------------------------------------------------------------
 *







|











|
|
<

|
<








>


<
|
|


















|







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, 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.
     */
    newSize += 1; /* For terminating nul */
    if (newSize > dsPtr->spaceAvl) {

	if (dsPtr->string == dsPtr->staticSpace) {
	    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 *)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, 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
 *
 *----------------------------------------------------------------------
 */

void
Tcl_DStringSetLength(
    Tcl_DString *dsPtr,		/* Structure describing dynamic string. */
    size_t length)			/* New length for dynamic string. */
{
    size_t newsize;




    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.
	 */




	newsize = dsPtr->spaceAvl * 2;
	if (length < newsize) {
	    dsPtr->spaceAvl = newsize;
	} else {
	    dsPtr->spaceAvl = length + 1;
	}
	if (dsPtr->string == dsPtr->staticSpace) {
	    char *newString = (char *)Tcl_Alloc(dsPtr->spaceAvl);







|

|

>
>
>







|
|
|
|


>
>
>
|







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. */
    Tcl_Size length)			/* New length for dynamic string. */
{
    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.
	 * 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 = 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

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_DStringGetResult --
 *







|







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, 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
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);

    Tcl_DStringFree(dsPtr);
    Tcl_DStringAppend(dsPtr, bytes, obj->length);
    Tcl_ResetResult(interp);
}

/*
 *----------------------------------------------------------------------
 *
 * TclDStringToObj --
 *
 *	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_DString *dsPtr)
{
    Tcl_Obj *result;

    if (dsPtr->string == dsPtr->staticSpace) {
	if (dsPtr->length == 0) {
	    TclNewObj(result);







|









|



















|







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);
    const char *bytes = TclGetString(obj);

    Tcl_DStringFree(dsPtr);
    Tcl_DStringAppend(dsPtr, bytes, obj->length);
    Tcl_ResetResult(interp);
}

/*
 *----------------------------------------------------------------------
 *
 * 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 *
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
    char *digits;
    char *end;

    /*
     * Handle NaN.
     */

    if (TclIsNaN(value)) {
	TclFormatNaN(value, dst);
	return;
    }

    /*
     * Handle infinities.
     */

    if (TclIsInfinite(value)) {
	/*
	 * Remember to copy the terminating NUL too.
	 */

	if (value < 0) {
	    memcpy(dst, "-Inf", 5);
	} else {







|








|







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 (isnan(value)) {
	TclFormatNaN(value, dst);
	return;
    }

    /*
     * Handle infinities.
     */

    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
	    *dst++ = '.';
	    while (c != '\0') {
		*dst++ = c;
		c = *++p;
	    }
	}

	sprintf(dst, "e%+d", exponent);
    } else {
	/*
	 * F format for others.
	 */

	if (exponent < 0) {
	    *dst++ = '0';







|







3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
	    *dst++ = '.';
	    while (c != '\0') {
		*dst++ = c;
		c = *++p;
	    }
	}

	snprintf(dst, TCL_DOUBLE_SPACE, "e%+d", exponent);
    } else {
	/*
	 * F format for others.
	 */

	if (exponent < 0) {
	    *dst++ = '0';
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
 * Side effects:
 *	The formatted characters are written into the storage pointer to by
 *	the "buffer" argument.
 *
 *----------------------------------------------------------------------
 */

size_t
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;
    static const char digits[] = "0123456789";

    /*
     * Generate the characters of the result backwards in the buffer.
     */

    intVal = (n < 0 ? -(Tcl_WideUInt)n : (Tcl_WideUInt)n);







|






|







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.
 *
 *----------------------------------------------------------------------
 */

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;
    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

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
				 * objPtr holds "end".
                                 * NOTE: this value may be TCL_INDEX_NONE. */
    Tcl_WideInt *widePtr)       /* Location filled in with a wide integer
                                 * representing an index. */
{
    int numType;
    ClientData cd;
    int code = TclGetNumberFromObj(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;



	    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;







|






|
|





>
>
>







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 */
    Tcl_WideInt endValue,       /* The value to be stored at *widePtr if
				 * objPtr holds "end".
                                 * NOTE: this value may be TCL_INDEX_NONE. */
    Tcl_WideInt *widePtr)       /* Location filled in with a wide integer
                                 * representing an index. */
{
    int 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
 *
 * 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)?.
 *








 * Value
 * 	TCL_OK
 *
 * 	    The index is stored at the address given by by 'indexPtr'. If
 * 	    'objPtr' has the value "end", the value stored is 'endValue'.
 *
 * 	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.
 *
 * Effect
 *
 * 	The object referenced by 'objPtr' is converted, as needed, to an
 * 	integer, wide integer, or end-based-index object.
 *
 *----------------------------------------------------------------------
 */

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
				 * "objPtr" holds "end". */
    size_t *indexPtr)		/* Location filled in with an integer
				 * representing an index. */
{
    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) {



	if ((wide < 0) && (endValue != TCL_INDEX_END)) {
	    *indexPtr = TCL_INDEX_NONE;


	} else if ((Tcl_WideUInt)wide > TCL_INDEX_END) {
	    *indexPtr = TCL_INDEX_END;
	} else {
	    *indexPtr = (size_t) 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:   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 *widePtr)       /* Location filled in with an integer
                                 * representing an index. */
{
    Tcl_ObjIntRep *irPtr;
    Tcl_WideInt offset = -1;	/* Offset in the "end-offset" expression - 1 */
    ClientData cd;

    while ((irPtr = TclFetchIntRep(objPtr, &endOffsetType)) == NULL) {
	Tcl_ObjIntRep ir;
	size_t length;
	const char *bytes = TclGetStringFromObj(objPtr, &length);

	if (*bytes != 'e') {
	    int numType;
	    const char *opPtr;
	    int len, 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 it's possible, do the full list parse. */
	            && (TCL_OK == Tcl_ListObjLength(NULL, objPtr, &len))
	            && (len > 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)) {
		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);
		    if (t1 == TCL_NUMBER_INT) {
			w1 = (*(Tcl_WideInt *)cd);
		    }

		    if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, opPtr + 1,
			    -1, NULL, TCL_PARSE_INTEGER_ONLY)) {
			/* ... value concludes with second valid integer */

			/* Save second integer as wide if possible */
			TclGetNumberFromObj(NULL, objPtr, &cd, &t2);
			if (t2 == TCL_NUMBER_INT) {
			    w2 = (*(Tcl_WideInt *)cd);
			}
		    }
		}
		/* Clear invalid intreps left by TclParseNumber */
		TclFreeIntRep(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) {







>
>
>
>
>
>
>
>
|


|
<







|

|
<











|
<
|
|



<
<




>
>
>
|
|
>
>
|
|
|
|




>
















|
>















|




|

|

|
|
|





|
















|
<

|
|




|









|





|



|





|
|







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.
 *
 * Results:
 * 	TCL_OK
 *
 * 	    The index is stored at the address given by by 'indexPtr'.

 *
 * 	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.
 *
 * Side effects:
 *
 * 	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. */
    Tcl_Size endValue,		/* The value corresponding to the "end" index */

    Tcl_Size *indexPtr)		/* Location filled in with an integer
				 * representing an index. May be NULL.*/
{
    Tcl_WideInt wide;



    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 */
	} 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 = (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. 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 */
    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. */
{
    Tcl_ObjInternalRep *irPtr;
    Tcl_WideInt offset = -1;	/* Offset in the "end-offset" expression - 1 */
    void *cd;

    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 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, TCL_INDEX_NONE, NULL) > 1)

		    /* If it's possible, do the full list parse. */
	            && (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, 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 */
		    Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t1);
		    if (t1 == TCL_NUMBER_INT) {
			w1 = (*(Tcl_WideInt *)cd);
		    }

		    if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, opPtr + 1,
			    TCL_INDEX_NONE, NULL, TCL_PARSE_INTEGER_ONLY)) {
			/* ... value concludes with second valid integer */

			/* Save second integer as wide if possible */
			Tcl_GetNumberFromObj(NULL, objPtr, &cd, &t2);
			if (t2 == TCL_NUMBER_INT) {
			    w2 = (*(Tcl_WideInt *)cd);
			}
		    }
		}
		/* 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
			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);

			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. */







|







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);
			}
			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
	    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)) {
		/* Not a recognized integer format */
		goto parseError;
	    }

	    /* Got an integer offset; pull it from where parser left it. */
	    TclGetNumberFromObj(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;







|





|







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)) {
		/* Not a recognized integer format */
		goto parseError;
	    }

	    /* Got an integer offset; pull it from where parser left it. */
	    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
		}
	    }
	}

    parseOK:
	/* Success. Store the new internal rep. */
	ir.wideValue = offset;
	Tcl_StoreIntRep(objPtr, &endOffsetType, &ir);
    }

    offset = irPtr->wideValue;

    if (offset == WIDE_MAX) {









	*widePtr = endValue + 1;
    } else if (offset == WIDE_MIN) {

	*widePtr = -1;
    } else if (endValue == (size_t)-1) {
	*widePtr = offset;
    } else if (offset < 0) {
	/* Different signs, sum cannot overflow */
	*widePtr = endValue + offset + 1;
    } else if (offset < WIDE_MAX) {

	*widePtr = offset;
    } else {

	*widePtr = WIDE_MAX;
    }
    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);
    }

    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclIndexEncode --




 *
 *      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 values that are integers as presented and it includes index
 *      arithmetic expressions. The absolute index values that can be
 *	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.
 *
 *      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







|





>
>
>
>
>
>
>
>
>
|

>

<
<

|


>


>














|









>
>
>
>



|

|
<
<
<
>
|
|
|
>
>
>
>
>
|







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
		}
	    }
	}

    parseOK:
	/* Success. Store the new internal rep. */
	ir.wideValue = offset;
	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 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) ? WIDE_MAX : endValue + 1;
    } else if (offset == WIDE_MIN) {
	/* -1 - position before first */
	*widePtr = -1;


    } else if (offset < 0) {
	/* end-(n-1) - Different signs, sum cannot overflow */
	*widePtr = endValue + offset + 1;
    } else if (offset < WIDE_MAX) {
	/* 0:WIDE_MAX-1 - plain old index. */
	*widePtr = offset;
    } else {
	/* Huh, what case remains here? */
	*widePtr = WIDE_MAX;
    }
    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", (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 Tcl_Size range.  Note that this includes
 *	index values that are integers as presented and it includes index
 *      arithmetic expressions.



 *
 *      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
 *      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.

 *
 * 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 *indexPtr)	/* Where to write the encoded answer, not NULL */
{
    Tcl_WideInt wide;
    int idx;



    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;
	}




	/*
	 * We parsed an end+offset index value.
	 * wide holds the offset value in the range WIDE_MIN...WIDE_MAX.



	 */





	if (wide > (unsigned)(irPtr ? TCL_INDEX_END : INT_MAX)) {
	    /*
	     * All end+postive or end-negative expressions



	     * always indicate "after the end".
	     */
	    idx = after;
	} else if (wide <= (irPtr ? INT_MAX : -1)) {
	    /* These indices always indicate "before the beginning */
	    idx = before;
	} else {
	    /* Encoded end-positive (or end+negative) are offset */
	    idx = (int)wide;
	}
    } else {

	return TCL_ERROR;











    }

















    *indexPtr = idx;
    return TCL_OK;









}

/*
 *----------------------------------------------------------------------
 *
 * 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
TclIndexDecode(
    int encoded,	/* Value to decode */
    size_t endValue)	/* Meaning of "end" to use, > TCL_INDEX_END */
{
    if (encoded > (int)TCL_INDEX_END) {
	return encoded;
    }

    if (endValue >= TCL_INDEX_END - encoded) {
	return endValue + encoded - TCL_INDEX_END;
    }
    return TCL_INDEX_NONE;
}





































/*
 *----------------------------------------------------------------------
 *
 * ClearHash --
 *
 *	Remove all the entries in the hash table *tablePtr.







<
<
<
<

|
>












|
|




>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
>
>
>
>
|
|
>
>
>
>

<
|
>
>
>

>
>
>
>
>
|

<
>
>
>
|


|
|


|



>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>

















|


|

|


>
|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *      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.
 *




 * Returns:
 *      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 */
    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, 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. */

	/*

	 * 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 > INT_MAX) {
	    /*

	     * 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 < 0) {
	    /* 4(a,b) (32-bit systems), 5(a,b) - before the beginning */
	    idx = before;
	} else {
	    /* 1(a,b) Encodable range */
	    idx = (int)wide;
	}
    } else {
	/* objPtr is not purely numeric (end etc.)  */

	/*
	 * 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", (void *)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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclIndexDecode(
    int encoded,	/* Value to decode */
    Tcl_Size endValue)	/* Meaning of "end" to use, > TCL_INDEX_END */
{
    if (encoded > TCL_INDEX_END) {
	return encoded;
    }
    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
 *	Frees a Tcl_HashTable.
 *
 *----------------------------------------------------------------------
 */

static void
FreeThreadHash(
    ClientData clientData)
{
    Tcl_HashTable *tablePtr = (Tcl_HashTable *)clientData;

    ClearHash(tablePtr);
    Tcl_DeleteHashTable(tablePtr);
    Tcl_Free(tablePtr);
}







|







4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
 *	Frees a Tcl_HashTable.
 *
 *----------------------------------------------------------------------
 */

static void
FreeThreadHash(
    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
 *	ProcessGlobalValue at exit.
 *
 *----------------------------------------------------------------------
 */

static void
FreeProcessGlobalValue(
    ClientData clientData)
{
    ProcessGlobalValue *pgvPtr = (ProcessGlobalValue *)clientData;

    pgvPtr->epoch++;
    pgvPtr->numBytes = 0;
    Tcl_Free(pgvPtr->value);
    pgvPtr->value = NULL;







|







4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
 *	ProcessGlobalValue at exit.
 *
 *----------------------------------------------------------------------
 */

static void
FreeProcessGlobalValue(
    void *clientData)
{
    ProcessGlobalValue *pgvPtr = (ProcessGlobalValue *)clientData;

    pgvPtr->epoch++;
    pgvPtr->numBytes = 0;
    Tcl_Free(pgvPtr->value);
    pgvPtr->value = NULL;
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
    if (pgvPtr->encoding) {
	Tcl_FreeEncoding(pgvPtr->encoding);
    }
    pgvPtr->encoding = encoding;

    /*
     * Fill the local thread copy directly with the Tcl_Obj value to avoid
     * loss of the intrep. 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);







|







4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
    if (pgvPtr->encoding) {
	Tcl_FreeEncoding(pgvPtr->encoding);
    }
    pgvPtr->encoding = encoding;

    /*
     * Fill the local thread copy directly with the Tcl_Obj value to avoid
     * 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
Tcl_Obj *
TclGetProcessGlobalValue(
    ProcessGlobalValue *pgvPtr)
{
    Tcl_Obj *value = NULL;
    Tcl_HashTable *cacheMap;
    Tcl_HashEntry *hPtr;
    size_t epoch = pgvPtr->epoch;

    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_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_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);







|















|
|
|
|
>







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
Tcl_Obj *
TclGetProcessGlobalValue(
    ProcessGlobalValue *pgvPtr)
{
    Tcl_Obj *value = NULL;
    Tcl_HashTable *cacheMap;
    Tcl_HashEntry *hPtr;
    Tcl_Size epoch = pgvPtr->epoch;

    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_MutexLock(&pgvPtr->mutex);
	    epoch = ++pgvPtr->epoch;
	    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);
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
 *----------------------------------------------------------------------
 */

int
TclReToGlob(
    Tcl_Interp *interp,
    const char *reStr,
    size_t reStrLen,
    Tcl_DString *dsPtr,
    int *exactPtr,
    int *quantifiersFoundPtr)
{
    int anchorLeft, anchorRight, lastIsStar, numStars;
    char *dsStr, *dsStrStart;
    const char *msg, *p, *strEnd, *code;







|







4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
 *----------------------------------------------------------------------
 */

int
TclReToGlob(
    Tcl_Interp *interp,
    const char *reStr,
    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
    }

    return TCL_OK;

  invalidGlob:
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
	Tcl_SetErrorCode(interp, "TCL", "RE2GLOB", code, NULL);
    }
    Tcl_DStringFree(dsPtr);
    return TCL_ERROR;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|












4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
    }

    return TCL_OK;

  invalidGlob:
    if (interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1));
	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
/*
 * 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
 *
 * 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 */
    TclHashObjKey,		/* hashKeyProc */
    CompareVarKeys,		/* compareKeysProc */
    AllocVarEntry,		/* allocEntryProc */
    FreeVarEntry		/* freeEntryProc */
};

static inline Var *	VarHashCreateVar(TclVarHashTable *tablePtr,









|
|
|
|
|


















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 © 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 */
    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

    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";



/*
 * 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)







<
<
<




















>
>







104
105
106
107
108
109
110



111
112
113
114
115
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 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
} ArrayVarHashTable;

/*
 * Forward references to functions defined later in this file:
 */

static void		AppendLocals(Tcl_Interp *interp, Tcl_Obj *listPtr,
			    Tcl_Obj *patternPtr, int includeLinks);

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,
			    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,
			    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,
			    const char **errMsgPtr, int *indexPtr);

static Tcl_DupInternalRepProc	DupLocalVarName;
static Tcl_FreeInternalRepProc	FreeLocalVarName;

static Tcl_FreeInternalRepProc	FreeParsedVarName;
static Tcl_DupInternalRepProc	DupParsedVarName;







|
>


















|











|
<
<









|







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
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,
			    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, 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 Tcl_ObjCmdProc ArrayDefaultCmd;


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, 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
 *			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

};

#define LocalSetIntRep(objPtr, index, namePtr)				\
    do {								\
	Tcl_ObjIntRep ir;						\
	Tcl_Obj *ptr = (namePtr);					\
	if (ptr) {Tcl_IncrRefCount(ptr);}				\
	ir.twoPtrValue.ptr1 = ptr;					\
	ir.twoPtrValue.ptr2 = INT2PTR(index);				\
	Tcl_StoreIntRep((objPtr), &localVarNameType, &ir);		\
    } while (0)

#define LocalGetIntRep(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;	\
    } while (0)

static const Tcl_ObjType parsedVarNameType = {
    "parsedVarName",
    FreeParsedVarName, DupParsedVarName, NULL, NULL

};

#define ParsedSetIntRep(objPtr, arrayPtr, elem)				\
    do {								\
	Tcl_ObjIntRep 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);		\
    } while (0)

#define ParsedGetIntRep(objPtr, parsed, array, elem)			\
    do {								\
	const Tcl_ObjIntRep *irPtr;					\
	irPtr = TclFetchIntRep((objPtr), &parsedVarNameType);		\
	(parsed) = (irPtr != NULL);					\
	(array) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr1 : NULL;		\
	(elem) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr2 : NULL;		\
    } while (0)

Var *
TclVarHashCreateVar(







|
>


|

|




|


|

|
|

|




|
>


|

|






|


|

|
|







244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
 *			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,
    TCL_OBJTYPE_V0
};

#define LocalSetInternalRep(objPtr, index, namePtr)				\
    do {								\
	Tcl_ObjInternalRep ir;						\
	Tcl_Obj *ptr = (namePtr);					\
	if (ptr) {Tcl_IncrRefCount(ptr);}				\
	ir.twoPtrValue.ptr1 = ptr;					\
	ir.twoPtrValue.ptr2 = INT2PTR(index);				\
	Tcl_StoreInternalRep((objPtr), &localVarNameType, &ir);		\
    } while (0)

#define LocalGetInternalRep(objPtr, index, name)				\
    do {								\
	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,
    TCL_OBJTYPE_V0
};

#define ParsedSetInternalRep(objPtr, arrayPtr, elem)				\
    do {								\
	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_StoreInternalRep((objPtr), &parsedVarNameType, &ir);		\
    } while (0)

#define ParsedGetInternalRep(objPtr, parsed, array, elem)			\
    do {								\
	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;		\
    } while (0)

Var *
TclVarHashCreateVar(
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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCleanupVar --







|







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, (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
    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)
		    !TclIsVarDeadHash(varPtr))) {
	if (VarHashRefCount(varPtr) == 0) {
	    Tcl_Free(varPtr);
	} else {
	    VarHashDeleteEntry(varPtr);
	}
    }
    if (arrayPtr != NULL && TclIsVarUndefined(arrayPtr) &&
	    TclIsVarInHash(arrayPtr) && !TclIsVarTraced(arrayPtr) &&
	    (VarHashRefCount(arrayPtr) == (unsigned)
		    !TclIsVarDeadHash(arrayPtr))) {
	if (VarHashRefCount(arrayPtr) == 0) {
	    Tcl_Free(arrayPtr);
	} else {
	    VarHashDeleteEntry(arrayPtr);
	}
    }







|









|







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) == (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) == (Tcl_Size)
		    !TclIsVarDeadHash(arrayPtr))) {
	if (VarHashRefCount(arrayPtr) == 0) {
	    Tcl_Free(arrayPtr);
	} else {
	    VarHashDeleteEntry(arrayPtr);
	}
    }
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
				 * 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
				 * 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
				 * 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. */
{







|


|







537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
				 * 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. */
    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. */
    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
				 * 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
				 * 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
				 * 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_Obj *namePtr, *arrayPtr, *elem;

    *arrayPtrPtr = NULL;

  restart:
    LocalGetIntRep(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.
     */

    ParsedGetIntRep(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);
		}
		return NULL;
	    }
	    part2Ptr = elem;
	    part1Ptr = arrayPtr;
	    goto restart;
    }

    if (!parsed) {
	/*
	 * part1Ptr is possibly an unparsed array element.
	 */

	size_t 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);
		    }
		    return NULL;
		}

		arrayPtr = Tcl_NewStringObj(part1, (part2 - part1));
		part2Ptr = Tcl_NewStringObj(part2 + 1,
			len - (part2 - part1) - 2);

		ParsedSetIntRep(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);
	}
	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);
	} 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
	     * 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
	     * 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);

	    /* Then wipe it */
	    TclFreeIntRep(cachedNamePtr);

	    /*
	     * Now go ahead and convert it the 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);
	}
    } else {
	/*
	 * At least mark part1Ptr as already parsed.
	 */

	ParsedSetIntRep(part1Ptr, NULL, NULL);
    }

  donePart1:
    while (TclIsVarLink(varPtr)) {
	varPtr = varPtr->value.linkPtr;
    }








|


|














|





|




















|


|










|













|











|








|


















|
















|




|



|








|


|






|






|







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. */
    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. */
    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;

    Tcl_Size localIndex;
    Tcl_Obj *namePtr, *arrayPtr, *elem;

    *arrayPtrPtr = NULL;

  restart:
    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 preparsed parts.
     */

    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", (char *)NULL);
		}
		return NULL;
	    }
	    part2Ptr = elem;
	    part1Ptr = arrayPtr;
	    goto restart;
    }

    if (!parsed) {
	/*
	 * part1Ptr is possibly an unparsed array element.
	 */

	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",
				(char *)NULL);
		    }
		    return NULL;
		}

		arrayPtr = Tcl_NewStringObj(part1, (part2 - part1));
		part2Ptr = Tcl_NewStringObj(part2 + 1,
			len - (part2 - part1) - 2);

		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), (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) {
	    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 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 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])
	     */
	    LocalSetInternalRep(part1Ptr, index, cachedNamePtr);

	    /* Then wipe it */
	    TclFreeInternalRep(cachedNamePtr);

	    /*
	     * Now go ahead and convert it the the "localVarName" type,
	     * since we suspect at least some use of the value as a
	     * varname and we want to resolve it quickly.
	     */
	    LocalSetInternalRep(cachedNamePtr, index, NULL);
	}
    } else {
	/*
	 * At least mark part1Ptr as already parsed.
	 */

	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
 *
 *	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:
 *		. 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.







|







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-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
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,
				 * 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;
    const char *varName = TclGetStringFromObj(varNamePtr, &varLen);

    varPtr = NULL;
    varNsPtr = NULL;		/* Set non-NULL if a nonlocal variable. */
    *indexPtr = -3;

    if (flags & TCL_GLOBAL_ONLY) {







|


















|
|







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. */
    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, 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

    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) == ':'));

	if (lookGlobal) {
	    *indexPtr = -1;
	    flags = (flags | TCL_GLOBAL_ONLY) & ~TCL_NAMESPACE_ONLY;
	} else {
	    flags = (flags | TCL_NAMESPACE_ONLY);
	    *indexPtr = -2;







|







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[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

		*indexPtr = -1;
	    } else {
		*indexPtr = -2;
	    }
	}
    } else {			/* Local var: look in frame varFramePtr. */
	int localCt = varFramePtr->numCompiledLocals;

	if (localCt > 0) {
	    Tcl_Obj **objPtrPtr = &varFramePtr->localCachePtr->varName0;
	    const char *localNameStr;
	    size_t 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)) {
			*indexPtr = i;
			return (Var *) &varFramePtr->compiledLocals[i];
		    }
		}
	    }
	}
	tablePtr = varFramePtr->varTablePtr;
	if (create) {
	    if (tablePtr == NULL) {
		tablePtr = (TclVarHashTable *)Tcl_Alloc(sizeof(TclVarHashTable));
		TclInitVarHashTable(tablePtr, NULL);

		varFramePtr->varTablePtr = tablePtr;
	    }
	    varPtr = VarHashCreateVar(tablePtr, varNamePtr, &isNew);
	} else {
	    varPtr = NULL;
	    if (tablePtr != NULL) {
		varPtr = VarHashFindVar(tablePtr, varNamePtr);







|




|








|











>







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. */
	Tcl_Size localCt = varFramePtr->numCompiledLocals;

	if (localCt > 0) {
	    Tcl_Obj **objPtrPtr = &varFramePtr->localCachePtr->varName0;
	    const char *localNameStr;
	    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)) {
			*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

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. */
    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
				 * 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
				 * 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);
	    }
	    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);
	    }
	    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);
	}
	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);
	    }
	}
    }
    return varPtr;
}

/*







|



|



|



















|














|










|




















|







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. */
    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. */
    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. */
    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, (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, (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, (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), (char *)NULL);
	    }
	}
    }
    return varPtr;
}

/*
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
    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
				 * 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");







|







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. */
    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");
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391



1392
1393
1394
1395
1396
1397
1398
    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
				 * 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;




    /*
     * Invoke any read traces that have been set for the variable.
     */

    if ((varPtr->flags & VAR_TRACED_READ)
	    || (arrayPtr && (arrayPtr->flags & VAR_TRACED_READ))) {







|







>
>
>







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
    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. */
    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

	if (avhtPtr->defaultObj) {
	    return avhtPtr->defaultObj;
	}
    }

    if (flags & TCL_LEAVE_ERR_MSG) {
	if (TclIsVarUndefined(varPtr) && arrayPtr
		&& !TclIsVarUndefined(arrayPtr)) {
	    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);
    if (TclIsVarUndefined(varPtr)) {
	TclCleanupVar(varPtr, arrayPtr);
    }
    return NULL;
}

/*







|
|















|







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) && 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", (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
 *	A variable's value may be changed.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SetObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *varValueObj;

    if (objc == 2) {







|







1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
 *	A variable's value may be changed.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_SetObjCmd(
    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) {
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
				 * 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
				 * 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");







|







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. */
    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");
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
				 * 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
				 * 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;







|







1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
				 * 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. */
    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
     */

    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);
	    } else {
		TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set",
			DANGLINGVAR, index);
		Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", 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);
	}
	goto earlyError;
    }



    /*
     * 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].







|



|


>
>
>
>
>
>
>
>
>
>
>










|



>
>







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", (char *)NULL);
	    } else {
		TclObjVarErrMsg(interp, part1Ptr, part2Ptr, "set",
			DANGLINGVAR, index);
		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", (void *)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", (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
    /*
     * 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);
    }
    if (TclIsVarUndefined(varPtr)) {
	TclCleanupVar(varPtr, arrayPtr);
    }
    return resultPtr;

  earlyError:







|







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", (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
				 * 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:
				 * 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");
    }







|







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? */
    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
				 * 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:
				 * 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;












    if (TclIsVarInHash(varPtr)) {
	VarHashRefCount(varPtr)++;
    }
    varValuePtr = TclPtrGetVarIdx(interp, varPtr, arrayPtr, part1Ptr,
	    part2Ptr, flags, index);
    if (TclIsVarInHash(varPtr)) {







|








>
>
>
>
>
>
>
>
>
>
>







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? */
    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", (void *)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
    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
				 * TCL_GLOBAL_ONLY, TCL_NAMESPACE_ONLY,
				 * TCL_LEAVE_ERR_MSG. */
{
    if (varPtr == NULL) {
	Tcl_Panic("varPtr must not be NULL");
    }
    if (part1Ptr == NULL) {







|







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. */
    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
 *----------------------------------------------------------------------
 */

int
TclPtrUnsetVarIdx(
    Tcl_Interp *interp,		/* Command interpreter in which varName is to
				 * be looked up. */
    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
				 * 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);













    /*
     * 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)++;
    }



    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);
	}
    }

    /*
     * 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.







|






|








>
>
>
>
>
>
>
>
>
>
>
>











>
>










|
|







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 *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. */
    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", (void *)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",
              ((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
			&dummyVar, &isNew);
		Tcl_SetHashValue(tPtr, tracePtr);
	    }
	}

	if ((dummyVar.flags & VAR_TRACED_UNSET)
		|| (arrayPtr && (arrayPtr->flags & VAR_TRACED_UNSET))) {














	    dummyVar.flags &= ~VAR_TRACE_ACTIVE;
	    TclObjCallVarTraces(iPtr, arrayPtr, &dummyVar, part1Ptr, part2Ptr,
		    (flags & (TCL_GLOBAL_ONLY|TCL_NAMESPACE_ONLY))
			    | 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.
	     */







>
>
>
>
>
>
>
>
>
>
>
>
>
>


|







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|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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UnsetObjCmd(
    TCL_UNUSED(ClientData),
    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;








|







2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UnsetObjCmd(
    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
 *	A variable's value may be changed.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_AppendObjCmd(
    TCL_UNUSED(ClientData),
    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. */







|







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(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
 *	A variable's value may be changed.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_LappendObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *varValuePtr, *newValuePtr;
    int numElems, createdNewObj;
    Var *varPtr, *arrayPtr;
    int result;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "varName ?value ...?");
	return TCL_ERROR;
    }
    if (objc == 2) {
	newValuePtr = Tcl_ObjGetVar2(interp, objv[1], NULL, 0);







|





|

|







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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Obj *varValuePtr, *newValuePtr;
    Tcl_Size numElems;
    Var *varPtr, *arrayPtr;
    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);
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
    *valuePtrPtr = valueObj;

    return donerc;
}

static int
ArrayForObjCmd(
    ClientData 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_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *varListObj, *arrayNameObj, *scriptObj;
    ArraySearch *searchPtr = NULL;
    Var *varPtr;
    int isArray, 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) {
	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);
	return TCL_ERROR;
    }

    arrayNameObj = objv[2];

    if (TCL_ERROR == LocateArray(interp, arrayNameObj, &varPtr, &isArray)) {
	return TCL_ERROR;







|









|







|
>














|






|







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(
    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(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj *varListObj, *arrayNameObj, *scriptObj;
    ArraySearch *searchPtr = NULL;
    Var *varPtr;
    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 (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", (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

    /*
     * Make sure that these objects (which we need throughout the body of the
     * loop) don't vanish.
     */

    varListObj = TclListObjCopy(NULL, objv[1]);



    scriptObj = objv[3];
    Tcl_IncrRefCount(scriptObj);

    /*
     * Run the script.
     */

    TclNRAddCallback(interp, ArrayForLoopCallback, searchPtr, varListObj,
	    arrayNameObj, scriptObj);
    return TCL_OK;
}

static int
ArrayForLoopCallback(
    ClientData 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;


    /*
     * Process the result from the previous execution of the script body.
     */

    done = TCL_ERROR;








>
>
>














|












|
>







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(
    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;
    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

    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);
	    varPtr->flags |= TCL_LEAVE_ERR_MSG;
	    result = done;
	}
	goto arrayfordone;
    }

    Tcl_ListObjGetElements(NULL, varListObj, &varc, &varv);



    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,







|






|
>
>
>







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", (char *)NULL);
	    varPtr->flags |= TCL_LEAVE_ERR_MSG;
	    result = done;
	}
	goto arrayfordone;
    }

    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayStartSearchCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr;
    int isArray;
    ArraySearch *searchPtr;







|







3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayStartSearchCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayAnyMoreCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *) interp;
    Var *varPtr;
    Tcl_Obj *varNameObj, *searchObj;







|







3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayAnyMoreCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayNextElementCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr;
    Tcl_Obj *varNameObj, *searchObj;
    ArraySearch *searchPtr;







|







3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayNextElementCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayDoneSearchCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *) interp;
    Var *varPtr;
    Tcl_Obj *varNameObj, *searchObj;







|







3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayDoneSearchCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayExistsCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Interp *iPtr = (Interp *)interp;
    int isArray;








|







3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayExistsCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayGetCmd(
    TCL_UNUSED(ClientData),
    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;

    int i, count, result, isArray;

    switch (objc) {
    case 2:
	varNameObj = objv[1];
	patternObj = NULL;
	break;
    case 3:







|









>
|







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(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 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
    }

    /*
     * Get the array values corresponding to each element name.
     */

    TclNewObj(tmpResObj);
    result = Tcl_ListObjGetElements(interp, nameLstObj, &count, &nameObjPtr);
    if (result != TCL_OK) {
	goto errorInArrayGet;
    }

    for (i=0 ; i<count ; i++) {
	nameObj = *nameObjPtr++;
	valueObj = Tcl_ObjGetVar2(interp, varNameObj, nameObj,







|







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 = 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayNamesCmd(
    TCL_UNUSED(ClientData),
    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 };
    Var *varPtr, *varPtr2;
    Tcl_Obj *nameObj, *resultObj, *patternObj;
    Tcl_HashSearch search;
    const char *pattern = NULL;
    int isArray, mode = OPT_GLOB;

    if ((objc < 2) || (objc > 4)) {
	Tcl_WrongNumArgs(interp, 1, objv, "arrayName ?mode? ?pattern?");
	return TCL_ERROR;
    }
    patternObj = (objc > 2 ? objv[objc-1] : NULL);








|







|




|







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(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} mode = OPT_GLOB;
    Var *varPtr, *varPtr2;
    Tcl_Obj *nameObj, *resultObj, *patternObj;
    Tcl_HashSearch search;
    const char *pattern = NULL;
    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
	    continue;
	}
	nameObj = VarHashGetKey(varPtr2);
	if (patternObj) {
	    const char *name = TclGetString(nameObj);
	    int matched = 0;

	    switch ((enum arrayNamesOptionsEnum) 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);







|







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 (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
	Tcl_Obj *nameObj;
	int dummy;

	if (TclIsVarUndefined(varPtr)) {
	    continue;
	}
	nameObj = VarHashGetKey(varPtr);
	hPtr = Tcl_CreateHashEntry(tablePtr, (char *) nameObj, &dummy);
	Tcl_SetHashValue(hPtr, nameObj);
    }
}

/*
 *----------------------------------------------------------------------
 *







|







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, 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArraySetCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *arrayNameObj;
    Tcl_Obj *arrayElemObj;
    Var *varPtr, *arrayPtr;
    int result, i;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "arrayName list");
	return TCL_ERROR;
    }

    if (TCL_ERROR == LocateArray(interp, objv[1], NULL, NULL)) {







|







|







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(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *arrayNameObj;
    Tcl_Obj *arrayElemObj;
    Var *varPtr, *arrayPtr;
    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
    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);
	return TCL_ERROR;
    }

    /*
     * Install the contents of the dictionary or list into the array.
     */

    arrayElemObj = objv[2];
    if (TclHasIntRep(arrayElemObj, &tclDictType) && arrayElemObj->bytes == NULL) {
	Tcl_Obj *keyPtr, *valuePtr;
	Tcl_DictSearch search;
	int done;


	if (Tcl_DictObjSize(interp, arrayElemObj, &done) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (done == 0) {
	    /*
	     * Empty, so we'll just force the array to be properly existing
	     * instead.
	     */

	    goto ensureArray;
	}







|








|



>

|


|







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), (char *)NULL);
	return TCL_ERROR;
    }

    /*
     * Install the contents of the dictionary or list into the array.
     */

    arrayElemObj = objv[2];
    if (TclHasInternalRep(arrayElemObj, &tclDictType) && arrayElemObj->bytes == NULL) {
	Tcl_Obj *keyPtr, *valuePtr;
	Tcl_DictSearch search;
	int done;
	Tcl_Size size;

	if (Tcl_DictObjSize(interp, arrayElemObj, &size) != TCL_OK) {
	    return TCL_ERROR;
	}
	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
	return TCL_OK;
    } else {
	/*
	 * Not a dictionary, so assume (and convert to, for backward-
	 * -compatibility reasons) a list.
	 */

	int elemLen;
	Tcl_Obj **elemPtrs, *copyListObj;


	result = TclListObjGetElements(interp, arrayElemObj,
		&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);
	    return TCL_ERROR;
	}
	if (elemLen == 0) {
	    goto ensureArray;





	}

	/*
	 * 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);



	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,







|

>

|
<






|




>
>
>
>
>









>
>
>







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.
	 */

	Tcl_Size elemLen;
	Tcl_Obj **elemPtrs, *copyListObj;
	Tcl_Size i;

	result = TclListObjLength(interp, arrayElemObj, &elemLen);

	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", (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
	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);
	    return TCL_ERROR;
	}
    }
    TclInitArrayVar(varPtr);
    return TCL_OK;
}








|







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", (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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArraySizeCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr;
    Tcl_HashSearch search;
    Var *varPtr2;







|







4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArraySizeCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayStatsCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Var *varPtr;
    Tcl_Obj *varNameObj;
    char *stats;







|







4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayStatsCmd(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayUnsetCmd(
    TCL_UNUSED(ClientData),
    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 isArray;

    switch (objc) {
    case 2:
	varNameObj = objv[1];
	patternObj = NULL;
	break;







|








|







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(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;
    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
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:
				 * 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 */







|







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. */
    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
			|| (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);
	    return TCL_ERROR;
	}
    }

    return TclPtrObjMakeUpvarIdx(interp, otherPtr, myNamePtr, myFlags, index);
}








|







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", (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
		 * 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);
		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);
	    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);
	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);
	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);
	    return TCL_ERROR;
	}

	linkPtr = varPtr->value.linkPtr;
	if (linkPtr == otherPtr) {
	    return TCL_OK;
	}







|


















|







|






|














|







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",
			(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), (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", (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", (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", (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
    }
    if (TclIsVarInHash(varPtr)) {
	if (!TclIsVarDeadHash(varPtr)) {
	    namePtr = VarHashGetKey(varPtr);
	    Tcl_AppendObjToObj(objPtr, namePtr);
	}
    } else if (iPtr->varFramePtr->procPtr) {
	int index = varPtr - iPtr->varFramePtr->compiledLocals;

	if (index >= 0 && index < iPtr->varFramePtr->numCompiledLocals) {
	    namePtr = localName(iPtr->varFramePtr, index);
	    Tcl_AppendObjToObj(objPtr, namePtr);
	}
    }
}












































































/*
 *----------------------------------------------------------------------
 *
 * 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_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;







|

|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















|







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) {
	Tcl_Size index = varPtr - iPtr->varFramePtr->compiledLocals;

	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", (void *)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", (void *)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", (void *)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(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
	 * 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) != ':'))) {
	    tail--;
	}
	if ((*tail == ':') && (tail > varName)) {
	    tail++;
	}

	if (tail == varName) {







|







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[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
 *	result in the interpreter's result object.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_VariableObjCmd(
    TCL_UNUSED(ClientData),
    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;







|







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(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
	    /*
	     * 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);
	    return TCL_ERROR;
	}

	if (varPtr == NULL) {
	    return TCL_ERROR;
	}








|







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", (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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UpvarObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    CallFrame *framePtr;
    int result, hasLevel;
    Tcl_Obj *levelObj;







|







5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_UpvarObjCmd(
    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
	 * 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);
	return TCL_ERROR;
    }

    /*
     * We've now finished with parsing levels; skip to the variable names.
     */








|







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), (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
	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);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteSearches --







|







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, (char *)NULL);
    return NULL;
}

/*
 *----------------------------------------------------------------------
 *
 * DeleteSearches --
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
    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)) {
	UnsetVarStruct(varPtr, NULL, iPtr, VarHashGetKey(varPtr), NULL, flags,
		-1);
	VarHashDeleteEntry(varPtr);
    }
    VarHashDeleteTable(tablePtr);
}








|







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)) {
	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
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_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,







|







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;
    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
 *   twoPtrValue.ptr2: index into locals table
 */

static void
FreeLocalVarName(
    Tcl_Obj *objPtr)
{
    int index;
    Tcl_Obj *namePtr;

    LocalGetIntRep(objPtr, index, namePtr);

    index++;	/* Compiler warning bait. */
    if (namePtr) {
	Tcl_DecrRefCount(namePtr);
    }
}

static void
DupLocalVarName(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dupPtr)
{
    int index;
    Tcl_Obj *namePtr;

    LocalGetIntRep(srcPtr, index, namePtr);
    if (!namePtr) {
	namePtr = srcPtr;
    }
    LocalSetIntRep(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);

    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);

    parsed++;				/* Silence compiler. */
    ParsedSetIntRep(dupPtr, arrayPtr, elem);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FindNamespaceVar -- MOVED OVER from tclNamesp.c
 *







|


|












|


|



|


















|
















|


|







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)
{
    Tcl_Size index;
    Tcl_Obj *namePtr;

    LocalGetInternalRep(objPtr, index, namePtr);

    index++;	/* Compiler warning bait. */
    if (namePtr) {
	Tcl_DecrRefCount(namePtr);
    }
}

static void
DupLocalVarName(
    Tcl_Obj *srcPtr,
    Tcl_Obj *dupPtr)
{
    Tcl_Size index;
    Tcl_Obj *namePtr;

    LocalGetInternalRep(srcPtr, index, namePtr);
    if (!namePtr) {
	namePtr = srcPtr;
    }
    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;

    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;

    ParsedGetInternalRep(srcPtr, parsed, arrayPtr, elem);

    parsed++;				/* Silence compiler. */
    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
    }
    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);
    }
    return (Tcl_Var) varPtr;
}

/*
 *----------------------------------------------------------------------
 *







|







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, (char *)NULL);
    }
    return (Tcl_Var) varPtr;
}

/*
 *----------------------------------------------------------------------
 *
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoVarsCmd(
    TCL_UNUSED(ClientData),
    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;







|







5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoVarsCmd(
    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;
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
			}
		    }
		    varPtr = VarHashNextVar(&search);
		}
	    }
	}
    } else if (iPtr->varFramePtr->procPtr != NULL) {
	AppendLocals(interp, listPtr, simplePatternPtr, 1);
    }

    if (simplePatternPtr) {
	Tcl_DecrRefCount(simplePatternPtr);
    }
    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;







|







6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
			}
		    }
		    varPtr = VarHashNextVar(&search);
		}
	    }
	}
    } else if (iPtr->varFramePtr->procPtr != NULL) {
	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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoGlobalsCmd(
    TCL_UNUSED(ClientData),
    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;







|







6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoGlobalsCmd(
    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
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoLocalsCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    Tcl_Obj *patternPtr, *listPtr;








|







6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
 *	error, the result is an error message.
 *
 *----------------------------------------------------------------------
 */

int
TclInfoLocalsCmd(
    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
    /*
     * 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);


































































































































































































    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 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. */

{
    Interp *iPtr = (Interp *) interp;
    Var *varPtr;
    int i, localVarCt, added;

    Tcl_Obj *objNamePtr;
    const char *varName;
    TclVarHashTable *localVarTablePtr;
    Tcl_HashSearch search;
    Tcl_HashTable addedTable;
    const char *pattern = patternPtr? TclGetString(patternPtr) : NULL;








|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|
>



|
>







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
    /*
     * 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, 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 justConstants)		/* 1 if just constants should be included. */
{
    Interp *iPtr = (Interp *) interp;
    Var *varPtr;
    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

	for (i = 0; i < localVarCt; i++, varNamePtr++) {
	    /*
	     * Skip nameless (temporary) variables and undefined variables.
	     */

	    if (*varNamePtr && !TclIsVarUndefined(varPtr)
		&& (includeLinks || !TclIsVarLink(varPtr))) {
		varName = TclGetString(*varNamePtr);
		if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {

		    Tcl_ListObjAppendElement(interp, listPtr, *varNamePtr);

		    if (includeLinks) {
			Tcl_CreateHashEntry(&addedTable, *varNamePtr, &added);
		    }
		}
	    }
	    varPtr++;
	}







|


>
|
>







6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584

	for (i = 0; i < localVarCt; i++, varNamePtr++) {
	    /*
	     * Skip nameless (temporary) variables and undefined variables.
	     */

	    if (*varNamePtr && !TclIsVarUndefined(varPtr)
		    && (includeLinks || !TclIsVarLink(varPtr))) {
		varName = TclGetString(*varNamePtr);
		if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {
	    	    if (!justConstants || TclIsVarConstant(varPtr)) {
			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
     */

    if ((pattern != NULL) && TclMatchIsTrivial(pattern)) {
	varPtr = VarHashFindVar(localVarTablePtr, patternPtr);
	if (varPtr != NULL) {
	    if (!TclIsVarUndefined(varPtr)
		    && (includeLinks || !TclIsVarLink(varPtr))) {

		Tcl_ListObjAppendElement(interp, listPtr,
			VarHashGetKey(varPtr));

		if (includeLinks) {
		    Tcl_CreateHashEntry(&addedTable, VarHashGetKey(varPtr),
			    &added);
		}
	    }
	}
	goto objectVars;







>
|
|
>







6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
     */

    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));
		}
		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
	    varPtr != NULL;
	    varPtr = VarHashNextVar(&search)) {
	if (!TclIsVarUndefined(varPtr)
		&& (includeLinks || !TclIsVarLink(varPtr))) {
	    objNamePtr = VarHashGetKey(varPtr);
	    varName = TclGetString(objNamePtr);
	    if ((pattern == NULL) || Tcl_StringMatch(varName, pattern)) {

		Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);

		if (includeLinks) {
		    Tcl_CreateHashEntry(&addedTable, objNamePtr, &added);
		}
	    }
	}
    }

  objectVars:
    if (!includeLinks) {
	return;
    }

    if (iPtr->varFramePtr->isProcCallFrame & FRAME_IS_METHOD) {


	Method *mPtr = (Method *)
		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 (added && (!pattern ||
			Tcl_StringMatch(TclGetString(objNamePtr), pattern))) {
		    Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);
		}
	    }
	    FOREACH_STRUCT(privatePtr, oPtr->privateVariables) {
		Tcl_CreateHashEntry(&addedTable, privatePtr->variableObj,
			&added);




		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 (added && (!pattern ||
			Tcl_StringMatch(TclGetString(objNamePtr), pattern))) {
		    Tcl_ListObjAppendElement(interp, listPtr, objNamePtr);
		}
	    }
	    FOREACH_STRUCT(privatePtr, clsPtr->privateVariables) {
		Tcl_CreateHashEntry(&addedTable, privatePtr->variableObj,
			&added);




		if (added && (!pattern ||
			Tcl_StringMatch(TclGetString(privatePtr->variableObj),
				pattern))) {
		    Tcl_ListObjAppendElement(interp, listPtr,
			    privatePtr->variableObj);
		}
	    }
	}
    }
    Tcl_DeleteHashTable(&addedTable);
}










































/*
 * 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;

}

static Tcl_HashEntry *
AllocVarEntry(
    TCL_UNUSED(Tcl_HashTable *),
    void *keyPtr)		/* Key to store in the hash table entry. */
{







>
|
>













>
>
|
<







>
>
>
>








>
>
>
>












>
>
>
>








>
>
>
>











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













>







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
	    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);
		}
		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 *) Tcl_ObjectContextMethod(context);

	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. */
{
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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayDefaultCmd(
    TCL_UNUSED(ClientData),
    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 };
    Tcl_Obj *arrayNameObj, *defaultValueObj;
    Var *varPtr, *arrayPtr;
    int isArray, option;

    /*
     * 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) {
    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);
	    return TCL_ERROR;
	}
	Tcl_SetObjResult(interp, defaultValueObj);
	return TCL_OK;

    case OPT_SET:
	if (objc != 4) {







|







|


|




















|














|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
ArrayDefaultCmd(
    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 } option;
    Tcl_Obj *arrayNameObj, *defaultValueObj;
    Var *varPtr, *arrayPtr;
    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 (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", (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
	     * 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);
	    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);
	    return TCL_ERROR;
	}

	if (!TclIsVarArray(varPtr)) {
	    TclInitArrayVar(varPtr);
	}
	defaultValueObj = objv[3];







|









|







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
	     * 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), (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", (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

    /*
     * Regular TclVarHashTable initialization.
     */

    arrayPtr->value.tablePtr = (TclVarHashTable *) tablePtr;
    TclInitVarHashTable(arrayPtr->value.tablePtr, TclGetVarNsPtr(arrayPtr));


    /*
     * Default value initialization.
     */

    tablePtr->defaultObj = NULL;
}







>







7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026

    /*
     * 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;
}

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
/*
 * tclZipfs.c --
 *
 *	Implementation of the ZIP filesystem used in TIP 430
 *	Adapted from the implentation for AndroWish.
 *
 * Copyright (c) 2016-2017 Sean Woods <[email protected]>
 * Copyright (c) 2013-2015 Christian Werner <[email protected]>
 *
 * 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.




 */

#include "tclInt.h"
#include "tclFileSystem.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





































#ifdef HAVE_ZLIB
#include "zlib.h"
#include "crypt.h"
#include "zutil.h"
#include "crc32.h"

#ifdef CFG_RUNTIME_DLLFILE

/*
** We are compiling as part of the core.
** TIP430 style zipfs prefix
*/

#define ZIPFS_VOLUME	  "//zipfs:/"
#define ZIPFS_VOLUME_LEN  9
#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"

#endif /* CFG_RUNTIME_DLLFILE */

/*
 * Various constants and offsets found in ZIP archive files
 */

#define ZIP_SIG_LEN			4





|

|
|








>
>
>
>




>
>









<



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|







|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90













91
92
93
94

95
96
97
98
99
100
101
/*
 * tclZipfs.c --
 *
 *	Implementation of the ZIP filesystem used in TIP 430
 *	Adapted from the implementation for AndroWish.
 *
 * Copyright © 2016-2017 Sean Woods <[email protected]>
 * Copyright © 2013-2015 Christian Werner <[email protected]>
 *
 * 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

#ifndef TBLS
#define TBLS 1
#endif

#if !defined(_WIN32) && !defined(NO_DLFCN_H)
#include <dlfcn.h>
#endif

/*
 * 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)

#ifdef HAVE_ZLIB
#include "zlib.h"
#include "crypt.h"
#include "zutil.h"
#include "crc32.h"

static const z_crc_t* crc32tab;

/*
** We are compiling as part of the core.
** TIP430 style zipfs prefix
*/

#define ZIPFS_VOLUME	  "//zipfs:/"
#define ZIPFS_ROOTDIR_DEPTH 3 /* Number of / in root mount */













#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"


/*
 * Various constants and offsets found in ZIP archive files
 */

#define ZIP_SIG_LEN			4

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196






197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232

233

234
235
236
237
238
239




240
241
242
243
244
245
246











247
248
249
250
251
252
253
254
255
256




257
258
259
260

261
262







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281






282
283
284
285
286
287
288
289
290
291
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
#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) \
    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 ZipReadInt(p) \
    ((p)[0] | ((p)[1] << 8) | ((p)[2] << 16) | ((p)[3] << 24))
#define ZipReadShort(p) \
    ((p)[0] | ((p)[1] << 8))

#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 */







/*
 * 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 */

    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 */
#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 */

    int compressMethod;		/* Compress method */
    int isDirectory;		/* Set to 1 if directory, or -1 if root */
    int depth;			/* Number of slashes in path. */
    int crc32;			/* CRC-32 */
    int timestamp;		/* Modification time */
    int isEncrypted;		/* True if data is encrypted */




    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.











 */

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
				 * channel */
    unsigned char *ubuf;	/* Pointer to the uncompressed data */




    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 */

    unsigned long keys[3];	/* Key for decryption */
} ZipChannel;








/*
 * 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
 * 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 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,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 inline int	DescribeMounted(Tcl_Interp *interp,
			    const char *mountPoint);




static inline int	ListMountPoints(Tcl_Interp *interp);






















static int		ZipfsAppHookFindTclInit(const char *archive);

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 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 void		ZipfsExitHandler(ClientData clientData);
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 void		ZipChannelWatchChannel(void *instanceData,
			    int mask);
static int		ZipChannelWrite(void *instanceData,
			    const char *buf, int toWrite, int *errloc);

/*
 * Define the ZIP filesystem dispatch table.







<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









>
>
>
>
>
>
















>
|




|












|
|
>
|
>

|

|


>
>
>
>







>
>
>
>
>
>
>
>
>
>
>





|
|
|
<

>
>
>
>
|


<
>


>
>
>
>
>
>
>







|










|
>
>
>
>
>
>




|
















>
>
|

>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>











>
>
>










>
|






|
|







157
158
159
160
161
162
163







164












165



166




167





















168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266

267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
#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 ZIP_CRYPT_HDR_LEN		12
















#define ZIP_MAX_FILE_SIZE		INT_MAX




#define DEFAULT_WRITE_MAX_SIZE		ZIP_MAX_FILE_SIZE






















/*
 * 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 */
    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 */
    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 */
    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;		/* 0 if file, 1 if directory, -1 if root */
    int depth;			/* Number of slashes in path. */
    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 */
    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*/

    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 isDirectory;		/* Set to 1 if directory, or -1 if root */
    int isEncrypted;		/* True if data is encrypted */

    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
 * 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; 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, 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 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 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,
			    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 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
    NULL, /* createDirectoryProc */
    NULL, /* removeDirectoryProc */
    NULL, /* deleteFileProc */
    NULL, /* copyFileProc */
    NULL, /* renameFileProc */
    NULL, /* copyDirectoryProc */
    NULL, /* lstatProc */
    (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. */
    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 */
};













































































































/*
 *-------------------------------------------------------------------------
 *
 * ReadLock, WriteLock, Unlock --
 *
 *	POSIX like rwlock functions to support multiple readers and single
 *	writer on internal structs.







|









|

|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    NULL, /* createDirectoryProc */
    NULL, /* removeDirectoryProc */
    NULL, /* deleteFileProc */
    NULL, /* copyFileProc */
    NULL, /* renameFileProc */
    NULL, /* copyDirectoryProc */
    NULL, /* lstatProc */
    (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. */
    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 */
};

/*
 *------------------------------------------------------------------------
 *
 * 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

TCL_DECLARE_MUTEX(ZipFSMutex)

#if TCL_THREADS

static Tcl_Condition ZipFSCond;

static 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
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
Unlock(void)
{
    Tcl_MutexLock(&ZipFSMutex);
    if (ZipFS.lock > 0) {
	--ZipFS.lock;
    } else if (ZipFS.lock < 0) {
	ZipFS.lock = 0;







|












|












|







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

TCL_DECLARE_MUTEX(ZipFSMutex)

#if TCL_THREADS

static Tcl_Condition ZipFSCond;

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 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 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
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
CountSlashes(
    const char *string)
{
    int count = 0;
    const char *p = string;

    while (*p != '\0') {
	if (*p == '/') {
	    count++;
	}
	p++;
    }
    return count;
}

/*
 *-------------------------------------------------------------------------
 *







































 * CanonicalPath --



























































 *



















 *	This function computes the canonical path from a directory and file











 *	name components into the specified Tcl_DString.














































































































































































 *
 * Results:
 *	Returns the pointer to the canonical path contained in the specified
 *	Tcl_DString.
 *
 * Side effects:
 *	Modifies the specified Tcl_DString.

 *
 *-------------------------------------------------------------------------
 */

static char *
CanonicalPath(
    const char *root,
    const char *tail,
    Tcl_DString *dsPtr,
    int inZipfs)
{

    char *path;
    int i, j, c, isUNC = 0, isVfs = 0, n = 0;
    int haveZipfsPath = 1;

#ifdef _WIN32
    if (tail[0] != '\0' && strchr(drvletters, tail[0]) && tail[1] == ':') {
	tail += 2;
	haveZipfsPath = 0;
    }
    /* UNC style path */
    if (tail[0] == '\\') {
	root = "";
	++tail;
	haveZipfsPath = 0;
    }
    if (tail[0] == '\\') {
	root = "/";
	++tail;
	haveZipfsPath = 0;
    }
#endif /* _WIN32 */

    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;
	}
    }

    if (isVfs != 2) {
	if (tail[0] == '/') {
	    if (isVfs != 1) {
		root = "";
	    }
	    ++tail;
	    isUNC = 0;
	}
	if (tail[0] == '/') {
	    if (isVfs != 1) {

		root = "/";
	    }
	    ++tail;
	    isUNC = 1;
	}
    }
    i = strlen(root);
    j = strlen(tail);

    switch (isVfs) {
    case 1:
	if (i > ZIPFS_VOLUME_LEN) {
	    Tcl_DStringSetLength(dsPtr, i + j + 1);
	    path = Tcl_DStringValue(dsPtr);
	    memcpy(path, root, i);
	    path[i++] = '/';
	    memcpy(path + i, tail, j);
	} else {
	    Tcl_DStringSetLength(dsPtr, i + j);
	    path = Tcl_DStringValue(dsPtr);
	    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);
	    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);
	    memcpy(path, root, i);
	    path[i++] = '/';
	    memcpy(path + i, tail, j);
	}

	break;
    }

#ifdef _WIN32
    for (i = 0; path[i] != '\0'; i++) {
	if (path[i] == '\\') {
	    path[i] = '/';
	}
    }
#endif /* _WIN32 */


    if (inZipfs) {
	n = ZIPFS_VOLUME_LEN;
    } else {

	n = 0;
    }


    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];

		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);

    return Tcl_DStringValue(dsPtr);
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSLookup --







|



|












|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
<


<
>

|

<

|
|
|
|
|

>
|
<
<
|
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
|
<
|
<
|
|
>
|
<
<
|
|
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
|
|
<
<
|
|
>
|
<
|
<
<
>
|

|
<
<
<
<
<
<
<
|
>
|
<
<
>
|

|
>
<
<
<

<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
>







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
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static inline size_t
CountSlashes(
    const char *string)
{
    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));
    }

    /* 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.
 *
 *-------------------------------------------------------------------------
 */

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:
 *    Pointer to normalized path.

 *
 * Side effects:

 *    Stores mapped path in dsPtr.
 *
 *------------------------------------------------------------------------
 */

static char *
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
	                                   by caller */
{
    const char *joiner[2];
    char *joinedPath;


    Tcl_Obj *unnormalizedObj;





    Tcl_Obj *normalizedObj;



    const char *normalizedPath;






    Tcl_Size normalizedLen;
    Tcl_DString dsJoin;












    assert(TclIsZipfsPath(mountPath));






    joiner[0] = mountPath;

    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] == ':') {


	joiner[1] += 2;
    }



#endif




    Tcl_DStringInit(&dsJoin);





    joinedPath = Tcl_JoinPath(2, joiner, &dsJoin);











    if (strncmp(ZIPFS_VOLUME, joinedPath, ZIPFS_VOLUME_LEN)) {
	/* path was not relative. Strip off the volume (e.g. UNC) */


	Tcl_Size numParts;
	const char **partsPtr;
	Tcl_SplitPath(path, &numParts, &partsPtr);
	Tcl_DStringFree(&dsJoin);

	partsPtr[0] = mountPath;


	(void)Tcl_JoinPath(numParts, partsPtr, &dsJoin);
	Tcl_Free(partsPtr);
    }
    unnormalizedObj = Tcl_DStringToObj(&dsJoin); /* Also resets dsJoin */







    Tcl_IncrRefCount(unnormalizedObj);
    normalizedObj = Tcl_FSGetNormalizedPath(interp, unnormalizedObj);
    if (normalizedObj == NULL) {


	/* Should not happen but continue... */
	normalizedObj = unnormalizedObj;
    }
    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_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
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static ZipEntry *
ZipFSLookup(
    char *filename)
{
    Tcl_HashEntry *hPtr;
    ZipEntry *z = NULL;

    hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, filename);
    if (hPtr) {
	z = (ZipEntry *)Tcl_GetHashValue(hPtr);
    }
    return z;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSLookupMount --
 *
 *	This function returns an indication if the given file name corresponds
 *	to a mounted ZIP archive file.
 *
 * Results:

 *	Returns true, if the given file name is a mounted ZIP archive file.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

#ifdef NEVER_USED
static int
ZipFSLookupMount(



































    char *filename)

{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;












    for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
	   hPtr = Tcl_NextHashEntry(&search)) {
	ZipFile *zf = Tcl_GetHashValue(hPtr);





















	if (strcmp(zf->mountPoint, filename) == 0) {

	    return 1;
	}
    }
    return 0;
}
#endif /* NEVER_USED */

























































/*
 *-------------------------------------------------------------------------
 *
 * ZipFSCloseArchive --
 *
 *	This function closes a mounted ZIP archive file.







|

|






|







|

<
|


>
|







<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>




>
>
>
>
>
>
>
>
>
>
>

|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>





|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static inline ZipEntry *
ZipFSLookup(
    const char *filename)
{
    Tcl_HashEntry *hPtr;
    ZipEntry *z = NULL;

    hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, filename);
    if (hPtr) {
	z = (ZipEntry *) Tcl_GetHashValue(hPtr);
    }
    return z;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSLookupZip --
 *

 *	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
 *	unknown/not mounted.
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */


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 = (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) &&
		 (strncmp(zf->mountPoint, path, pathLen) == 0)) {
	    /* Matched standard mount */
	    return 1;
	}
    }
    return 0;
}

/*
 *-------------------------------------------------------------------------
 *
 * 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
	    Tcl_Free(zf->ptrToFree);
	    zf->ptrToFree = NULL;
	}
	zf->data = NULL;
	return;
    }





#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;
    }
#endif /* _WIN32 */

    if (zf->ptrToFree) {
	Tcl_Free(zf->ptrToFree);
	zf->ptrToFree = NULL;
    }
    if (zf->chan) {
	Tcl_CloseEx(interp, zf->chan, 0);
	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.
 *
 * 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.

 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSFindTOC(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    int needZip,
    ZipFile *zf)
{
    size_t i;

    unsigned char *p, *q;








    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) {
		break;
	    }
	    p -= ZIP_SIG_LEN;
	} else {
	    --p;
	}
    }
    if (p < zf->data) {





	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);
    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);
	}
	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)) {







	if (!needZip) {

	    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);
	}
	goto error;
    }








    zf->baseOffset = zf->passOffset = p - q;


    zf->directoryOffset = p - zf->data;

    q = p;






    for (i = 0; i < zf->numFiles; i++) {










	int pathlen, comlen, extra;




	if (q + ZIP_CENTRAL_HEADER_LEN > zf->data + zf->length) {

	    ZIPFS_ERROR(interp, "wrong header length");
	    if (interp) {
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "HDR_LEN", NULL);
	    }
	    goto error;


	}
	if (ZipReadInt(q) != ZIP_CENTRAL_HEADER_SIG) {
	    ZIPFS_ERROR(interp, "wrong header signature");
	    if (interp) {
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "HDR_SIG", NULL);
	    }




	    goto error;
	}
	pathlen = ZipReadShort(q + ZIP_CENTRAL_PATHLEN_OFFS);

	comlen = ZipReadShort(q + ZIP_CENTRAL_FCOMMENTLEN_OFFS);
	extra = ZipReadShort(q + ZIP_CENTRAL_EXTRALEN_OFFS);
	q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;






    }
    q = zf->data + zf->baseOffset;

    if ((zf->baseOffset >= 6) && (ZipReadInt(q - 4) == ZIP_PASSWORD_END_SIG)) {


	i = q[-5];
	if (q - 5 - i > zf->data) {

	    zf->passBuf[0] = i;
	    memcpy(zf->passBuf + 1, q - 5 - i, i);
	    zf->passOffset -= i ? (5 + i) : 0;
	}
    }
    return TCL_OK;

  error:
    ZipFSCloseArchive(interp, zf);
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * 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.

 *
 * 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.
 *
 *-------------------------------------------------------------------------
 */







>
>
>
>











|








|











|






|
|
>










|
>
|
>

>
>
>
>
>
>
|
|
|
|


|

|


|
>
>
>
>
>




|
>
|
>
>
>
|
|
|
>
>
>
>
>
|
>
>
>
>
|






|
|
|
<
|
>
>
>
>
>
>
>
>
>
|
|
|
>
>
|
>
>
>
>
>
>
>

>
|


|
|
|
|
<
|
>
>
>
>
>
>
>
>
|
>
>
|
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
|
>
|
|
|
|
<
>
>

|
<
<
<
|
>
>
>
>
|
|
|
>
|
<
<
>
>
>
>
>
>
|
|
>
|
>
>

|
>

|



<

<
<
|















|
>







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
	    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;
    }
#endif /* _WIN32 */

    if (zf->ptrToFree) {
	Tcl_Free(zf->ptrToFree);
	zf->ptrToFree = NULL;
    }
    if (zf->chan) {
	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. 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.  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, 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.
     */

    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;
	    }
	    eocdPtr -= ZIP_SIG_LEN;
	} else {
	    --eocdPtr;
	}
    }
    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, "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");
	ZIPFS_ERROR_CODE(interp, "EMPTY");
	goto error;
    }


    /*
     * 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->directoryOffset = zf->baseOffset = zf->passOffset = zf->length;
	    return TCL_OK;
	}
	ZIPFS_ERROR(interp, "archive directory truncated");
	ZIPFS_ERROR_CODE(interp, "NO_DIR");
	goto error;
    }


    /*
     * 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;

    /*
     * 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 ((dirEntry-cdirStart) + ZIP_CENTRAL_HEADER_LEN > (ptrdiff_t)zf->directorySize) {
	    ZIPFS_ERROR(interp, "truncated directory");
	    ZIPFS_ERROR_CODE(interp, "TRUNC_DIR");
	    goto error;
	}
	if (ZipReadInt(start, end, dirEntry) != ZIP_CENTRAL_HEADER_SIG) {
	    ZIPFS_ERROR(interp, "wrong header signature");
	    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;
	}

	if (localhdr_off < minoff) {
	    minoff = localhdr_off;
	}
	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.
     */

    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];
	passPtr = q - 5 - i;
	if (passPtr >= start && passPtr + i < end) {
	    zf->passBuf[0] = i;
	    memcpy(zf->passBuf + 1, passPtr, i);
	    zf->passOffset -= i ? (5 + i) : 0;
	}
    }




    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. 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

    zf->nameLength = 0;
    zf->isMemBuffer = 0;
#ifdef _WIN32
    zf->data = NULL;
    zf->mountHandle = INVALID_HANDLE_VALUE;
#else /* !_WIN32 */
    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;





    zf->chan = Tcl_OpenFileChannel(interp, zipname, "rb", 0);
    if (!zf->chan) {
	return TCL_ERROR;
    }










    if (Tcl_GetChannelHandle(zf->chan, TCL_READABLE, &handle) != TCL_OK) {









	zf->length = Tcl_Seek(zf->chan, 0, SEEK_END);
	if (zf->length == TCL_IO_FAILURE) {
	    ZIPFS_POSIX_ERROR(interp, "seek error");
	    goto error;
	}


	if ((zf->length - ZIP_CENTRAL_END_LEN)
		> (64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) {
	    ZIPFS_ERROR(interp, "illegal file size");
	    if (interp) {
		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);
	if (!zf->ptrToFree) {
	    ZIPFS_ERROR(interp, "out of memory");
	    if (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");
	    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 */
	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");
	    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) {
	    ZIPFS_POSIX_ERROR(interp, "file mapping failed");
	    goto error;
	}
#endif /* _WIN32 */
    }
    return ZipFSFindTOC(interp, needZip, zf);






  error:
    ZipFSCloseArchive(interp, zf);
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *







 * ZipFSRootNode --









 *





































































































 *	This function generates the root node for a ZIPFS filesystem.

 *
 * Results:
 *	TCL_OK on success, TCL_ERROR otherwise with an error message placed
 *	into the given "interp" if it is not NULL.
 *
 * Side effects:
 *	...
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSCatalogFilesystem(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    ZipFile *zf0,
    const char *mountPoint,	/* Mount point path. */
    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;
    ZipEntry *z;
    Tcl_HashEntry *hPtr;
    Tcl_DString ds, dsm, fpBuf;
    unsigned char *q;





    /*
     * 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,
			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.

     */




    Tcl_DStringInit(&ds);

    Tcl_DStringInit(&dsm);


    if (strcmp(mountPoint, "/") == 0) {
	mountPoint = "";
    } else {
	mountPoint = CanonicalPath("", mountPoint, &dsm, 1);
    }
    hPtr = Tcl_CreateHashEntry(&ZipFS.zipHash, mountPoint, &isNew);
    if (!isNew) {
	if (interp) {
	    zf = (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);
	}
	Unlock();
	ZipFSCloseArchive(interp, zf0);


	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);
	return TCL_ERROR;

    }
    Unlock();

    *zf = *zf0;
    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);
    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';
    }

    if (mountPoint[0] != '\0') {
	hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, mountPoint, &isNew);
	if (isNew) {
	    z = (ZipEntry *)Tcl_Alloc(sizeof(ZipEntry));
	    Tcl_SetHashValue(hPtr, z);

	    z->tnext = NULL;
	    z->depth = CountSlashes(mountPoint);

	    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->next = zf->entries;
	    zf->entries = z;
	}
    }
    q = zf->data + zf->directoryOffset;
    Tcl_DStringInit(&fpBuf);
    for (i = 0; i < zf->numFiles; i++) {


	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);
	Tcl_DStringSetLength(&ds, 0);
	Tcl_DStringAppend(&ds, (char *) q + ZIP_CENTRAL_HEADER_LEN, pathlen);
	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)) {
	    goto nextent;
	}
	nbcompr = ZipReadInt(lq + ZIP_LOCAL_COMPLEN_OFFS);
	if (!isdir && (nbcompr == 0)
		&& (ZipReadInt(lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0)
		&& (ZipReadInt(lq + ZIP_LOCAL_CRC32_OFFS) == 0)) {
	    gq = q;
	    nbcompr = ZipReadInt(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);
	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 (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));
	z->name = NULL;
	z->tnext = NULL;
	z->depth = CountSlashes(fullpath);

	z->zipFilePtr = zf;
	z->isDirectory = isdir;
	z->isEncrypted = (ZipReadShort(lq + ZIP_LOCAL_FLAGS_OFFS) & 1)

		&& (nbcompr > 12);
	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->timestamp = DosTimeDate(dosDate, dosTime);
	    z->numBytes = ZipReadInt(gq + ZIP_CENTRAL_UNCOMPLEN_OFFS);

	    z->compressMethod = ZipReadShort(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->timestamp = DosTimeDate(dosDate, dosTime);
	    z->numBytes = ZipReadInt(lq + ZIP_LOCAL_UNCOMPLEN_OFFS);

	    z->compressMethod = ZipReadShort(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);


	} 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_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;
		    zd->tnext = NULL;
		    zd->depth = CountSlashes(dir);

		    zd->zipFilePtr = zf;
		    zd->isDirectory = 1;
		    zd->isEncrypted = 0;
		    zd->offset = z->offset;
		    zd->crc32 = 0;
		    zd->timestamp = z->timestamp;
		    zd->numBytes = zd->numCompressedBytes = 0;
		    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;
		    }
		}
	    }
	}
    nextent:
	q += pathlen + comlen + extra + ZIP_CENTRAL_HEADER_LEN;
    }

    Tcl_DStringFree(&fpBuf);
    Tcl_DStringFree(&ds);
    Tcl_FSMountsChanged(NULL);
    Unlock();
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipfsSetup --







|






>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>

|



>
>
|
|

|
<
<






|

<
|
<
<







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
>
|
<
<
<
<
<
<
<
<
>
>
>
|
<
<
|
<
<
<
<
<
|
<
<
<
<
<


>
>
>
>
>








>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>



|


|







|
|




|
|
|


|

>
>
>
>








|
|
|
<
<
<




<
<

<
<
>


>
>
>
|
>
|
>
>
|
<
|
<
|



|

|
|


|
>
>


<
<
<
<
<
|
<
>
|
<
>
|
<
<
<
|
<

>

|

|
<
<











>



|


<

>


<

<
<
<

<
|
>
>
>
>
>
>







>
>





|
|
|

|
<









|
|


|

|
|

|



|
|



>















|
<
















>

|
|
<
<

>


|
>
|


|
|
|

|
>
|
>

|
|
|

|
>
|
>


<




>
>
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
|
|
|

|
|
|
|
|
|
|
|
|
>
>
>
|
|
|
|
<
|
>
|
|
<
|
<
|
<
|
<
|
|
|
|
|
|
|
<






>



<







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

    zf->nameLength = 0;
    zf->isMemBuffer = 0;
#ifdef _WIN32
    zf->data = NULL;
    zf->mountHandle = INVALID_HANDLE_VALUE;
#else /* !_WIN32 */
    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 (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 == (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) ||
		(zf->length - ZIP_CENTRAL_END_LEN) >
			(64 * 1024 * 1024 - ZIP_CENTRAL_END_LEN)) {
	    ZIPFS_ERROR(interp, "illegal file size");
	    ZIPFS_ERROR_CODE(interp, "FILE_SIZE");


	    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);
	if (!zf->ptrToFree) {

	    ZIPFS_MEM_ERROR(interp);


	    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;
	}















    }



    /*
     * Close the Tcl channel. If the file was mapped, the mapping is








     * 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.
     */


    Tcl_Close(interp, zf->chan);





    zf->chan = NULL;





    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.
 *
 *-------------------------------------------------------------------------
 */

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. On error, frees zf!!
 *
 * Side effects:
 *	Will acquire and release the write lock.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSCatalogFilesystem(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    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 isNew;
    size_t i, pwlen;
    ZipFile *zf0;
    ZipEntry *z;
    Tcl_HashEntry *hPtr;
    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 (IsPasswordValid(interp, passwd, pwlen) != TCL_OK) {
	    ZipFSCloseArchive(interp, zf);
	    Tcl_Free(zf);



	    return TCL_ERROR;
	}
    }



    /*


     * 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");
	ZIPFS_ERROR_CODE(interp, "BAD_ZIP");
	ZipFSCloseArchive(interp, zf);
	Tcl_Free(zf);
	return TCL_ERROR;
    }


    WriteLock();


    hPtr = Tcl_CreateHashEntry(&ZipFS.zipHash, mountPoint, &isNew);
    if (!isNew) {
	if (interp) {
	    zf0 = (ZipFile *) Tcl_GetHashValue(hPtr);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s is already mounted on %s", zf0->name, mountPoint));
	    ZIPFS_ERROR_CODE(interp, "MOUNTED");
	}
	Unlock();
	ZipFSCloseArchive(interp, zf);
	Tcl_DStringFree(&ds);
	Tcl_Free(zf);
	return TCL_ERROR;
    }







    /*
     * Convert to a real archive descriptor.

     */




    zf->mountPoint = (char *) Tcl_GetHashKey(&ZipFS.zipHash, hPtr);

    zf->mountPointLen = strlen(zf->mountPoint);

    zf->nameLength = strlen(zipname);
    zf->name = (char *) Tcl_Alloc(zf->nameLength + 1);
    memcpy(zf->name, zipname, zf->nameLength + 1);



    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 = AllocateZipEntry();
	    Tcl_SetHashValue(hPtr, z);


	    z->depth = CountSlashes(mountPoint);
	    assert(z->depth >= ZIPFS_ROOTDIR_DEPTH);
	    z->zipFilePtr = zf;
	    z->isDirectory = (zf->baseOffset == 0) ? 1 : -1; /* root marker */

	    z->offset = zf->baseOffset;



	    z->compressMethod = ZIP_COMPMETH_STORED;

	    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(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);
	path = DecodeZipEntryText(q + ZIP_CENTRAL_HEADER_LEN, pathlen, &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(start, end, q + ZIP_CENTRAL_LOCALHDR_OFFS);
	if ((lq < start) || (lq + ZIP_LOCAL_HEADER_LEN > end)) {
	    goto nextent;
	}
	nbcompr = ZipReadInt(start, end, lq + ZIP_LOCAL_COMPLEN_OFFS);
	if (!isdir && (nbcompr == 0)
		&& (ZipReadInt(start, end, lq + ZIP_LOCAL_UNCOMPLEN_OFFS) == 0)
		&& (ZipReadInt(start, end, lq + ZIP_LOCAL_CRC32_OFFS) == 0)) {
	    gq = q;
	    nbcompr = ZipReadInt(start, end, gq + ZIP_CENTRAL_COMPLEN_OFFS);
	}
	offs = (lq - zf->data)
		+ ZIP_LOCAL_HEADER_LEN
		+ 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);
	    if (ZipFSLookup(Tcl_DStringValue(&ds2))) {

		/* 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 = MapPathToZipfs(interp, mountPoint, path, &fpBuf);
	z = AllocateZipEntry();


	z->depth = CountSlashes(fullpath);
	assert(z->depth >= ZIPFS_ROOTDIR_DEPTH);
	z->zipFilePtr = zf;
	z->isDirectory = isdir;
	z->isEncrypted =
		(ZipReadShort(start, end, lq + ZIP_LOCAL_FLAGS_OFFS) & 1)
		&& (nbcompr > ZIP_CRYPT_HDR_LEN);
	z->offset = offs;
	if (gq) {
	    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(start, end,
		    gq + ZIP_CENTRAL_UNCOMPLEN_OFFS);
	    z->compressMethod = ZipReadShort(start, end,
		    gq + ZIP_CENTRAL_COMPMETH_OFFS);
	} else {
	    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(start, end,
		    lq + ZIP_LOCAL_UNCOMPLEN_OFFS);
	    z->compressMethod = ZipReadShort(start, end,
		    lq + ZIP_LOCAL_COMPMETH_OFFS);
	}
	z->numCompressedBytes = nbcompr;

	hPtr = Tcl_CreateHashEntry(&ZipFS.fileHash, fullpath, &isNew);
	if (!isNew) {
	    /* should not happen but skip it anyway */
	    Tcl_Free(z);
	    goto nextent;
	}

	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 (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->depth = CountSlashes(dir);
		assert(zd->depth > ZIPFS_ROOTDIR_DEPTH);
		zd->zipFilePtr = zf;
		zd->isDirectory = 1;

		zd->offset = z->offset;

		zd->timestamp = z->timestamp;

		zd->compressMethod = ZIP_COMPMETH_STORED;

		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);

    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipfsSetup --
1449
1450
1451
1452
1453
1454
1455

1456
1457
1458
1459
1460



1461
1462
1463
1464
1465
1466
1467
     */

    Tcl_MutexLock(&ZipFSMutex);
    Tcl_ConditionWait(&ZipFSCond, &ZipFSMutex, &t);
    Tcl_MutexUnlock(&ZipFSMutex);
#endif /* TCL_THREADS */


    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.initialized = 1;
}

/*
 *-------------------------------------------------------------------------
 *
 * ListMountPoints --







>





>
>
>







2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
     */

    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
 *
 * Side effects:
 *	Interpreter result may be updated.
 *
 *-------------------------------------------------------------------------
 */

static inline int
ListMountPoints(
    Tcl_Interp *interp)
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    ZipFile *zf;












    for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
	    hPtr = Tcl_NextHashEntry(&search)) {






	if (!interp) {
	    return TCL_OK;
	}
	zf = (ZipFile *)Tcl_GetHashValue(hPtr);



	Tcl_AppendElement(interp, zf->mountPoint);




















	Tcl_AppendElement(interp, zf->name);


    }
    return (interp ? TCL_OK : TCL_BREAK);


}





/*
 *-------------------------------------------------------------------------
 *
 * 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
DescribeMounted(
    Tcl_Interp *interp,
    const char *mountPoint)
{
    Tcl_HashEntry *hPtr;
    ZipFile *zf;

    if (interp) {
	hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint);
	if (hPtr) {
	    zf = (ZipFile *)Tcl_GetHashValue(hPtr);
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(zf->name, -1));
	    return TCL_OK;
	}
    }
    return (interp ? TCL_OK : TCL_BREAK);
}








|






>

>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
|
|
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
<
>
>
|
>
|
>
>
>



















|




|
|

<
<
|
<







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
 *
 * Side effects:
 *	Interpreter result may be updated.
 *
 *-------------------------------------------------------------------------
 */

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));
    }
    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);
	}

	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 int
DescribeMounted(
    Tcl_Interp *interp,
    const char *mountPoint)
{
    if (interp) {
	ZipFile *zf = ZipFSLookupZip(mountPoint);



	if (zf) {

	    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
 *
 *-------------------------------------------------------------------------
 */

int
TclZipfs_Mount(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */

    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;


    ReadLock();
    if (!ZipFS.initialized) {
	ZipfsSetup();
    }

    /*
     * No mount point, so list all mount points and what is mounted there.
     */

    if (!mountPoint) {
	int ret = ListMountPoints(interp);








	Unlock();
	return ret;
    }

    /*
     * Mount point but no file, so describe what is mounted at that mount
     * point.
     */

    if (!zipname) {





	DescribeMounted(interp, mountPoint);
	Unlock();


	return TCL_OK;


    }
    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);

	    }
	    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);
	}
	return TCL_ERROR;
    }
    if (ZipFSOpenArchive(interp, zipname, 1, zf) != TCL_OK) {
	Tcl_Free(zf);
	return TCL_ERROR;
    }
    if (ZipFSCatalogFilesystem(interp, zf, mountPoint, passwd, zipname)
	    != TCL_OK) {
	Tcl_Free(zf);
	return TCL_ERROR;
    }
    Tcl_Free(zf);
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_MountBuffer --
 *
 *	This procedure is invoked to mount a given ZIP archive file on a given
 *	mountpoint with optional ZIP password.
 *
 * 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,
    size_t datalen,

    int copy)
{
    ZipFile *zf;
    int result;







    ReadLock();
    if (!ZipFS.initialized) {
	ZipfsSetup();
    }

    /*
     * No mount point, so list all mount points and what is mounted there.
     */


    if (!mountPoint) {
	int ret = ListMountPoints(interp);
	Unlock();
	return ret;
    }

    /*
     * 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.

     */

    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);

	}
	return TCL_ERROR;



    }
    zf->isMemBuffer = 1;
    zf->length = datalen;

    if (copy) {
	zf->data = (unsigned char *)Tcl_AttemptAlloc(datalen);
	if (!zf->data) {
	    if (interp) {
		Tcl_AppendResult(interp, "out of memory", (char *) NULL);
		Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
	    }
	    return TCL_ERROR;

	}
	memcpy(zf->data, data, datalen);
	zf->ptrToFree = zf->data;
    } else {
	zf->data = data;
	zf->ptrToFree = NULL;
    }
    zf->passBuf[0] = 0;	/* stop valgrind cries */
    if (ZipFSFindTOC(interp, 0, zf) != TCL_OK) {
	return TCL_ERROR;





    }

    result = ZipFSCatalogFilesystem(interp, zf, mountPoint, NULL,

	    "Memory Buffer");

    Tcl_Free(zf);
    return result;
}

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_Unmount --
 *







>

<




>










|
|
>
>
>
>
>
>
>
>



|
<
<
<
<


>
>
>
>
>
|

>
>
|
>
>
|
|

<
<
<
|
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
>
>
|
>
|
>
>
|
>
|
<
|
|
<
<
>
|
|
<
|
<
|
<
|
<

<
<
<
<
|
|
|








|














<
|

>



|

>
>
>
>
>
>





<
<
<
|
>
|
|



|
<
<
<
<

<
<
<
<
<




>

|
<
|
>
|
|
|
>
|
<
>
>
>



>


|
|
<
|
<
|
>




|


<
|
|
>
>
>
>
>

>
|
>
|
>
|
|







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
 *
 *-------------------------------------------------------------------------
 */

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 *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 == 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);





    if (!zipname) {
	/*
	 * Mount point but no file, so describe what is mounted at that mount
	 * point.
	 */

	ret = DescribeMounted(interp, mountPoint);
	Unlock();
    } else {
	/* Have both a mount point and a file (name) to mount there. */

	Tcl_Obj *zipPathObj;
	Tcl_Obj *normZipPathObj;

	Unlock();




	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! */
		    }

		}
	    }


	    Tcl_DecrRefCount(normZipPathObj);
	    if (ret == TCL_OK && interp) {
		Tcl_DStringResult(interp, &ds);

	    }

	}

	Tcl_DecrRefCount(zipPathObj);

    }





    Tcl_DStringFree(&ds);
    return ret;
}

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_MountBuffer --
 *
 *	This procedure is invoked to mount a given ZIP archive file on a given
 *	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 void *data,
    size_t datalen,
    const char *mountPoint,	/* Mount point path. */
    int copy)
{
    ZipFile *zf;
    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();
    }




    Tcl_DString ds;
    Tcl_DStringInit(&ds);
    ret = NormalizeMountPoint(interp, mountPoint, &ds);
    if (ret != TCL_OK) {
	Unlock();
	return ret;
    }
    mountPoint = Tcl_DStringValue(&ds);










    Unlock();

    /*
     * Have both a mount point and data to mount there.
     * What's the magic about 64 * 1024 * 1024 ?
     */
    ret = TCL_ERROR;

    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;
    }

    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 == NULL) {
	    ZipFSCloseArchive(interp, zf);

	    Tcl_Free(zf);

	    ZIPFS_MEM_ERROR(interp);
	    goto done;
	}
	memcpy(zf->data, data, datalen);
	zf->ptrToFree = zf->data;
    } else {
	zf->data = (unsigned char *)data;
	zf->ptrToFree = NULL;
    }

    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) {
	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

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;



    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);

    hPtr = Tcl_FindHashEntry(&ZipFS.zipHash, mountPoint);
    /* don't report no-such-mount as an error */
    if (!hPtr) {
	goto done;
    }

    zf = (ZipFile *)Tcl_GetHashValue(hPtr);
    if (zf->numOpen > 0) {
	ZIPFS_ERROR(interp, "filesystem is 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);
    }
    ZipFSCloseArchive(interp, zf);
    Tcl_DeleteExitHandler(ZipfsExitHandler, zf);
    Tcl_Free(zf);
    unmounted = 1;

  done:
    Unlock();

    if (unmounted) {
	Tcl_FSMountsChanged(NULL);
    }
    return ret;
}

/*







<



>
>











|
>
>
|







|


>




<
<
<
<
<
|
<
<
>
>
>
>
|
|
<

|


>


>







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

int
TclZipfs_Unmount(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    const char *mountPoint)	/* Mount point path. */
{
    ZipFile *zf;

    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.
     */

    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);
    if (zf->numOpen > 0) {
	ZIPFS_ERROR(interp, "filesystem is busy");
	ZIPFS_ERROR_CODE(interp, "BUSY");
	ret = TCL_ERROR;
	goto done;
    }
    Tcl_DeleteHashEntry(hPtr);








    /*
     * 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_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
 *	A ZIP archive file is mounted, resources are allocated.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMountObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{



    if (objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv,
		 "?mountpoint? ?zipfile? ?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);






}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSMountBufferObjCmd --
 *
 *	This procedure is invoked to process the [zipfs mount_data] command.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	A ZIP archive file is mounted, resources are allocated.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMountBufferObjCmd(
    TCL_UNUSED(ClientData),
    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;

    if (objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? ?data?");
	return TCL_ERROR;
    }
    if (objc < 2) {
	int ret;

	ReadLock();
	ret = ListMountPoints(interp);
	Unlock();
	return ret;
    }

    mountPoint = TclGetString(objv[1]);
    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);
}

/*
 *-------------------------------------------------------------------------
 *
 * 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_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *)) /*objv*/
{




    Tcl_SetObjResult(interp, Tcl_NewStringObj(ZIPFS_VOLUME, -1));
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *







|




>
>



|


|
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
>
>
>




















|




|
|
|

|
|


<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<



|




















|

|
|

>
>
>
>







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
 *	A ZIP archive file is mounted, resources are allocated.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMountObjCmd(
    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,
		 "?zipfile? ?mountpoint? ?password?");
	return TCL_ERROR;
    }
    /*
     * 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.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	A ZIP archive file is mounted, resources are allocated.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMountBufferObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *mountPoint = NULL;	/* Mount point path. */
    unsigned char *data = NULL;
    Tcl_Size length;

    if (objc != 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "data mountpoint");
	return TCL_ERROR;
    }


    data = Tcl_GetBytesFromObj(interp, objv[1], &length);






    mountPoint = Tcl_GetString(objv[2]);








    if (data == NULL) {
	return TCL_ERROR;
    }
    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(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    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
 *	A mounted ZIP archive file is unmounted, resources are free'd.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSUnmountObjCmd(
    TCL_UNUSED(ClientData),
    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");
	return TCL_ERROR;
    }
    return TclZipfs_Unmount(interp, TclGetString(objv[1]));
}

/*
 *-------------------------------------------------------------------------







|




<

|







2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715

2716
2717
2718
2719
2720
2721
2722
2723
2724
 *	A mounted ZIP archive file is unmounted, resources are free'd.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSUnmountObjCmd(
    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, "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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkKeyObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int len, i = 0;
    char *pw, passBuf[264];



    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "password");
	return TCL_ERROR;
    }
    pw = TclGetString(objv[1]);
    len = strlen(pw);
    if (len == 0) {
	return TCL_OK;
    }
    if ((len > 255) || strchr(pw, 0xff)) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("illegal password", -1));
	return TCL_ERROR;
    }



    while (len > 0) {
	int ch = pw[len - 1];

	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);




    return TCL_OK;






}

/*
 *-------------------------------------------------------------------------
 *
 * ZipAddFile --
 *
 *	This procedure is used by ZipFSMkZipOrImgCmd() 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.



 *
 * 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,
    const char *passwd,		/* Password for encoding the file, or NULL if
				 * the file is to be unprotected. */
    char *buf,
    int bufsize,
    Tcl_HashTable *fileHash)

{


    Tcl_Channel in;
    Tcl_HashEntry *hPtr;
    ZipEntry *z;
    z_stream stream;

    const char *zpath;


    int crc, flush, zpathlen;
    size_t nbyte, nbytecompr, len, olen, align = 0;
    Tcl_WideInt pos[3];

    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++;
    }
    if (!zpath || (zpath[0] == '\0')) {
	return TCL_OK;
    }











    zpathlen = strlen(zpath);
    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);

	return TCL_ERROR;
    }
    in = Tcl_OpenFileChannel(interp, path, "rb", 0);
    if (!in) {

#ifdef _WIN32
	/* hopefully a directory */
	if (strcmp("permission denied", Tcl_PosixError(interp)) == 0) {
	    Tcl_CloseEx(interp, in, 0);
	    return TCL_OK;
	}
#endif /* _WIN32 */
	Tcl_CloseEx(interp, in, 0);
	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);





    crc = 0;
    nbyte = nbytecompr = 0;
    while (1) {
	len = Tcl_Read(in, buf, bufsize);
	if (len == TCL_IO_FAILURE) {

	    if (nbyte == 0 && errno == EISDIR) {
		Tcl_CloseEx(interp, in, 0);
		return TCL_OK;
	    }

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("read error on \"%s\": %s",
		    path, Tcl_PosixError(interp)));
	    Tcl_CloseEx(interp, in, 0);
	    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);

	return TCL_ERROR;
    }






    pos[0] = Tcl_Tell(out);






    memset(buf, '\0', ZIP_LOCAL_HEADER_LEN);
    memcpy(buf + ZIP_LOCAL_HEADER_LEN, zpath, zpathlen);
    len = zpathlen + ZIP_LOCAL_HEADER_LEN;
    if (Tcl_Write(out, buf, len) != len) {
    wrerr:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"write error on %s: %s", path, Tcl_PosixError(interp)));

	Tcl_CloseEx(interp, in, 0);

	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 = 4 + ((len + pos[0]) & 3);
	ZipWriteShort(abuf, 0xffff);
	ZipWriteShort(abuf + 2, align - 4);
	ZipWriteInt(abuf + 4, 0x03020100);
	if (Tcl_Write(out, (const char *) abuf, align) != align) {
	    goto wrerr;
	}
    }





    if (passwd) {
	int i, ch, tmp;
	unsigned char kvbuf[24];
	Tcl_Obj *ret;

	init_keys(passwd, keys, crc32tab);
	for (i = 0; i < 12 - 2; i++) {
	    double r;

	    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);
		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));
	}
	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));
	}
	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) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "write error on %s: %s", path, Tcl_PosixError(interp)));
	    Tcl_CloseEx(interp, in, 0);
	    return TCL_ERROR;
	}
	memcpy(keys0, keys, sizeof(keys0));
	nbytecompr += 12;
    }





    Tcl_Flush(out);
    pos[2] = Tcl_Tell(out);





    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);

	return TCL_ERROR;
    }

    do {
	len = Tcl_Read(in, buf, bufsize);
	if (len == TCL_IO_FAILURE) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "read error on %s: %s", path, Tcl_PosixError(interp)));
	    deflateEnd(&stream);
	    Tcl_CloseEx(interp, in, 0);
	    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) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"deflate error on %s", path));
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DEFLATE", NULL);
		deflateEnd(&stream);
		Tcl_CloseEx(interp, in, 0);

		return TCL_ERROR;
	    }
	    olen = sizeof(obuf) - stream.avail_out;
	    if (passwd) {
		size_t 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;

	    }
	    nbytecompr += olen;
	} while (stream.avail_out == 0);
    } while (flush != Z_FINISH);
    deflateEnd(&stream);





    Tcl_Flush(out);
    pos[1] = 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]) {
	seekErr:
	    Tcl_CloseEx(interp, in, 0);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "seek error: %s", Tcl_PosixError(interp)));


	    return TCL_ERROR;
	}
	nbytecompr = (passwd ? 12 : 0);
	while (1) {
	    len = Tcl_Read(in, buf, bufsize);
	    if (len == TCL_IO_FAILURE) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"read error on \"%s\": %s",
			path, Tcl_PosixError(interp)));
		Tcl_CloseEx(interp, in, 0);
		return TCL_ERROR;
	    } else if (len == 0) {
		break;
	    }
	    if (passwd) {
		size_t 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)));
		Tcl_CloseEx(interp, in, 0);
		return TCL_ERROR;
	    }
	    nbytecompr += len;
	}
	compMeth = ZIP_COMPMETH_STORED;






	Tcl_Flush(out);
	pos[1] = Tcl_Tell(out);
	Tcl_TruncateChannel(out, pos[1]);
    }
    Tcl_CloseEx(interp, in, 0);



    hPtr = Tcl_CreateHashEntry(fileHash, zpath, &isNew);
    if (!isNew) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"non-unique path name \"%s\"", path));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "DUPLICATE_PATH", NULL);
	return TCL_ERROR;
    }






    z = (ZipEntry *)Tcl_Alloc(sizeof(ZipEntry));

    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->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->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);
    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]) {
	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]) {
	Tcl_DeleteHashEntry(hPtr);
	Tcl_Free(z);
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"seek error: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *





















































































 * ZipFSMkZipOrImgObjCmd --
 *
 *	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.




 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	A new ZIP archive file or image file is written.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkZipOrImgObjCmd(
    Tcl_Interp *interp,		/* Current interpreter. */
    int isImg,



    int isList,








    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */

{
    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;
    ZipEntry *z;
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_HashTable fileHash;
    char *strip = NULL, *pw = NULL, passBuf[264], buf[4096];



    /*
     * Caller has verified that the number of arguments is correct.
     */

    passBuf[0] = 0;
    if (objc > (isList ? 3 : 4)) {
	pw = TclGetString(objv[isList ? 3 : 4]);
	pwlen = strlen(pw);
	if ((pwlen > 255) || strchr(pw, 0xff)) {
	    Tcl_SetObjResult(interp,
		    Tcl_NewStringObj("illegal password", -1));
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_PASS", NULL);
	    return TCL_ERROR;
	}


    }
    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];
	cmd[0] = Tcl_NewListObj(2, cmd + 1);
	Tcl_IncrRefCount(cmd[0]);
	if (Tcl_EvalObjEx(interp, cmd[0], TCL_EVAL_DIRECT) != TCL_OK) {
	    Tcl_DecrRefCount(cmd[0]);

	    return TCL_ERROR;
	}
	Tcl_DecrRefCount(cmd[0]);
	list = Tcl_GetObjResult(interp);
	Tcl_IncrRefCount(list);
    }

    if (Tcl_ListObjGetElements(interp, list, &lobjc, &lobjv) != TCL_OK) {
	Tcl_DecrRefCount(list);
	return TCL_ERROR;
    }
    if (isList && (lobjc % 2)) {
	Tcl_DecrRefCount(list);
	Tcl_SetObjResult(interp,
		Tcl_NewStringObj("need even number of elements", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "LIST_LENGTH", NULL);
	return TCL_ERROR;
    }
    if (lobjc == 0) {
	Tcl_DecrRefCount(list);
	Tcl_SetObjResult(interp, Tcl_NewStringObj("empty archive", -1));
	Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "EMPTY", NULL);
	return TCL_ERROR;
    }




    out = Tcl_OpenFileChannel(interp, TclGetString(objv[1]), "wb", 0755);
    if (out == NULL) {
	Tcl_DecrRefCount(list);
	return TCL_ERROR;
    }
    if (pwlen <= 0) {
	pw = NULL;

	pwlen = 0;



    }
    if (isImg) {
	ZipFile *zf, zf0;
	int isMounted = 0;
	const char *imgName;

	if (isList) {
	    imgName = (objc > 4) ? TclGetString(objv[4]) :
		    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++;







|




|
|
>
>





|
<



<
|


>
>
>



|
<



|
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>

>
>
>
>
>
>







|



>
>
>














|
|
>
|


|
|
|
>

>
>




>
|
>
>

|
|
>









|
|
|

|



>
>
>
>
>
>
>
>
>
>
|


|
|
>


|

>



|



|


<


<



<


>
>
>
>
>




|
>

|


>

|
|










|
|
>


>
>
>
>
>
>
|
>
>
>
>
>
>

|


|

|
>
|
>


<
<

|
|
|
|

>
>
>
>
>
|
|
|
|

|


>
>
>
>
>


|
<


|
<
|
<
<
<
<
<
<
|


<
<
<
<
<
<
<
<
<
<
<
|



|
|



|
|
|
<
|
<
<


|

>
>
>
>
>

|
>
>
>
>
>








|
|
|
>


>


|
<
<

|
<








|

|
|

|
>




|







<
<

<
<
>





>
>
>
>
>

|
>




>



|

<


>
>


|


|
<
<
|
<
<




|







<
|
<
<




>
>
>
>
>
>

|
|

|
>
>

|


|
|



>
>
>
>
>
|
>

<
<
<
<
<

|





<
|
<




|
|
<
<
<
<
<
<
<
<
|
|














|












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|




|
>
>
>
>











|

|
>
>
>
|
>
>
>
>
>
>
>
>
|
|
>


|
|
|
>
>
>
>
>
>
|





>
>






|
|
<
<
|
<
<


>
>
|
<
<
<
<
<
|
<
|
<
<
|
<
>


<
<
<

>
|



|

<
|
|




|
|


>
>
>
>
|




|
<
>
|
>
>
>
|





|
|
|
<
<
<
<







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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkKeyObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    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 = TclGetStringFromObj(objv[1], &len);

    if (len == 0) {
	return TCL_OK;
    }

    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];

	len--;
    }
    passBuf[i] = i;
    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 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. */
    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,			/* 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 *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;
    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.
     */

    zpathTcl = name;
    while (zpathTcl && zpathTcl[0] == '/') {
	zpathTcl++;
    }
    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(zpathExt);
    if (zpathlen + ZIP_CENTRAL_HEADER_LEN > bufsize) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"path too long for \"%s\"", TclGetString(pathObj)));
	ZIPFS_ERROR_CODE(interp, "PATH_LEN");
	Tcl_DStringFree(&zpathDs);
	return TCL_ERROR;
    }
    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_Close(interp, in);
	    return TCL_OK;
	}
#endif /* _WIN32 */
	Tcl_Close(interp, in);
	return TCL_ERROR;
    } else {

	Tcl_StatBuf statBuf;


	if (Tcl_FSStat(pathObj, &statBuf) != -1) {
	    mtime = statBuf.st_mtime;
	}

    }
    Tcl_ResetResult(interp);

    /*
     * Compute the CRC.
     */

    crc = 0;
    nbyte = nbytecompr = 0;
    while (1) {
	len = Tcl_Read(in, buf, bufsize);
	if (len < 0) {
	    Tcl_DStringFree(&zpathDs);
	    if (nbyte == 0 && errno == EISDIR) {
		Tcl_Close(interp, in);
		return TCL_OK;
	    }
	readErrorWithChannelOpen:
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf("read error on \"%s\": %s",
		    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",
		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).
     */

    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, zpathExt, zpathlen);
    len = zpathlen + ZIP_LOCAL_HEADER_LEN;
    if (Tcl_Write(out, buf, len) != len) {
    writeErrorWithChannelOpen:
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"write error on \"%s\": %s",
		TclGetString(pathObj), Tcl_PosixError(interp)));
	Tcl_Close(interp, in);
	Tcl_DStringFree(&zpathDs);
	return TCL_ERROR;
    }



    /*
     * 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 + 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 writeErrorWithChannelOpen;
	}
    }

    /*
     * Set up encryption if we were asked to.
     */

    if (passwd) {
	int i, ch, tmp;
	unsigned char kvbuf[2*ZIP_CRYPT_HDR_LEN];


	init_keys(passwd, keys, crc32tab);
	for (i = 0; i < ZIP_CRYPT_HDR_LEN - 2; i++) {

	    if (RandomChar(interp, i, &ch) != TCL_OK) {






		Tcl_Close(interp, in);
		return TCL_ERROR;
	    }











	    kvbuf[i + ZIP_CRYPT_HDR_LEN] = UCHAR(zencode(keys, crc32tab, ch, tmp));
	}
	Tcl_ResetResult(interp);
	init_keys(passwd, keys, crc32tab);
	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, ZIP_CRYPT_HDR_LEN);
	memset(kvbuf, 0, sizeof(kvbuf));
	if (len != ZIP_CRYPT_HDR_LEN) {

	    goto writeErrorWithChannelOpen;


	}
	memcpy(keys0, keys, sizeof(keys0));
	nbytecompr += ZIP_CRYPT_HDR_LEN;
    }

    /*
     * Save where we've got to in case we need to just store this file.
     */

    Tcl_Flush(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\"", 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 < 0) {


	    deflateEnd(&stream);
	    goto readErrorWithChannelOpen;

	}
	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 == Z_STREAM_ERROR) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"deflate error on \"%s\"", TclGetString(pathObj)));
		ZIPFS_ERROR_CODE(interp, "DEFLATE");
		deflateEnd(&stream);
		Tcl_Close(interp, in);
		Tcl_DStringFree(&zpathDs);
		return TCL_ERROR;
	    }
	    olen = sizeof(obuf) - stream.avail_out;
	    if (passwd) {
		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)) {


		deflateEnd(&stream);


		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);
    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, dataStartOffset, SEEK_SET) != dataStartOffset) {
	seekErr:

	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "seek error: %s", Tcl_PosixError(interp)));
	    Tcl_Close(interp, in);
	    Tcl_DStringFree(&zpathDs);
	    return TCL_ERROR;
	}
	nbytecompr = (passwd ? ZIP_CRYPT_HDR_LEN : 0);
	while (1) {
	    len = Tcl_Read(in, buf, bufsize);
	    if (len < 0) {


		goto readErrorWithChannelOpen;


	    } else if (len == 0) {
		break;
	    }
	    if (passwd) {
		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) {

		goto writeErrorWithChannelOpen;


	    }
	    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);
	dataEndOffset = Tcl_Tell(out);
	Tcl_TruncateChannel(out, dataEndOffset);
    }
    Tcl_Close(interp, in);
    Tcl_DStringFree(&zpathDs);
    zpathExt = NULL;

    hPtr = Tcl_CreateHashEntry(fileHash, zpathTcl, &isNew);
    if (!isNew) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"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 = AllocateZipEntry();
    Tcl_SetHashValue(hPtr, z);





    z->isEncrypted = (passwd ? 1 : 0);
    z->offset = headerStartOffset;
    z->crc32 = crc;
    z->timestamp = mtime;
    z->numBytes = nbyte;
    z->numCompressedBytes = nbytecompr;
    z->compressMethod = compMeth;

    z->name = (char *) Tcl_GetHashKey(fileHash, hPtr);


    /*
     * Write final local header information.
     */

    SerializeLocalEntryHeader(start, end, (unsigned char *) buf, z,








	    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, 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;
}

/*
 *-------------------------------------------------------------------------
 *
 * 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. 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
ZipFSMkZipOrImg(
    Tcl_Interp *interp,		/* Current interpreter. */
    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 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 (passwordObj != NULL) {
	pw = TclGetStringFromObj(passwordObj, &pwlen);


	if (IsPasswordValid(interp, pw, pwlen) != TCL_OK) {


	    return TCL_ERROR;
	}
	if (pwlen == 0) {
	    pw = NULL;
	}





    }

    if (dirRoot != NULL) {


	list = ZipFSFind(interp, dirRoot);

	if (!list) {
	    return TCL_ERROR;
	}



    }
    Tcl_IncrRefCount(list);
    if (TclListObjLength(interp, list, &lobjc) != TCL_OK) {
	Tcl_DecrRefCount(list);
	return TCL_ERROR;
    }
    if (mappingList && (lobjc % 2)) {
	Tcl_DecrRefCount(list);

	ZIPFS_ERROR(interp, "need even number of elements");
	ZIPFS_ERROR_CODE(interp, "LIST_LENGTH");
	return TCL_ERROR;
    }
    if (lobjc == 0) {
	Tcl_DecrRefCount(list);
	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_FSOpenFileChannel(interp, targetFile, "wb", 0755);
    if (out == NULL) {
	Tcl_DecrRefCount(list);
	return TCL_ERROR;
    }


    /*
     * 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;

	// TODO: normalize the origin file name
	imgName = (originFile != NULL) ? TclGetString(originFile) :
		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
	/*
	 * Check for mounted image.
	 */

	WriteLock();
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
		hPtr = Tcl_NextHashEntry(&search)) {
	    zf = (ZipFile *)Tcl_GetHashValue(hPtr);
	    if (strcmp(zf->name, imgName) == 0) {
		isMounted = 1;
		zf->numOpen++;
		break;
	    }
	}
	Unlock();

	if (!isMounted) {
	    zf = &zf0;

	}
	if (isMounted || ZipFSOpenArchive(interp, imgName, 0, zf) == TCL_OK) {




	    if (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);
		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 (!in) {
		memset(passBuf, 0, sizeof(passBuf));
		Tcl_DecrRefCount(list);
		Tcl_CloseEx(interp, out, 0);
		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);

	}
	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);
		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;




	path = TclGetString(lobjv[i]);

	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;
	}
	if (ZipAddFile(interp, path, name, out, pw, buf, sizeof(buf),
		&fileHash) != TCL_OK) {
	    goto done;
	}
    }





    pos[1] = Tcl_Tell(out);
    count = 0;
    for (i = 0; i < (size_t) lobjc; i += (isList ? 2 : 1)) {
	const char *path, *name;

	path = TclGetString(lobjv[i]);
	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);
	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));
	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);
	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)) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "write error: %s", Tcl_PosixError(interp)));

	    goto done;
	}

	count++;
    }





    Tcl_Flush(out);
    pos[2] = 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);
    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);
    } else {
	Tcl_CloseEx(interp, out, 0);
    }
    Tcl_DecrRefCount(list);
    for (hPtr = Tcl_FirstHashEntry(&fileHash, &search); hPtr;
	    hPtr = Tcl_NextHashEntry(&search)) {
	z = (ZipEntry *)Tcl_GetHashValue(hPtr);
	Tcl_Free(z);
	Tcl_DeleteHashEntry(hPtr);
    }
    Tcl_DeleteHashTable(&fileHash);
    return ret;
}


























































































































































































/*
 *-------------------------------------------------------------------------
 *
 * ZipFSMkZipObjCmd, ZipFSLMkZipObjCmd --
 *
 *	These procedures are invoked to process the [zipfs mkzip] and [zipfs
 *	lmkzip] commands.  See description of ZipFSMkZipOrImgCmd().
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See description of ZipFSMkZipOrImgCmd().
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkZipObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{


    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);
	return TCL_ERROR;
    }



    return ZipFSMkZipOrImgObjCmd(interp, 0, 0, objc, objv);

}

static int
ZipFSLMkZipObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{


    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);
	return TCL_ERROR;
    }


    return ZipFSMkZipOrImgObjCmd(interp, 0, 1, objc, objv);

}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSMkImgObjCmd, ZipFSLMkImgObjCmd --
 *
 *	These procedures are invoked to process the [zipfs mkimg] and [zipfs
 *	lmkimg] commands.  See description of ZipFSMkZipOrImgCmd().
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See description of ZipFSMkZipOrImgCmd().
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkImgObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{


    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);
	return TCL_ERROR;
    }




    return ZipFSMkZipOrImgObjCmd(interp, 1, 0, objc, objv);

}

static int
ZipFSLMkImgObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{


    if (objc < 3 || objc > 5) {
	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);
	return TCL_ERROR;
    }



    return ZipFSMkZipOrImgObjCmd(interp, 1, 1, objc, objv);

}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSCanonicalObjCmd --
 *







|







>


>


>
>
>
>
|





|

















<
<
<
<
<





<
|
<


|


<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
>
|







|






<
<
<
<
<
|
<
<
>
>
>

<
>
|
|
<
<
|
|
<
<
|
<
|
<
<
>
>
|
>
|



|




>
>
>
>
>
|

|
|
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<




|
|
|
|
|
<
>
|
|
|
<
<
<
|
<
<
<
<
<
<
|
|
|


>


>


>
>
>
>
>

|
<
<
<
>
|
<
<
<
<










|

|




|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|





|






|




>
>





<
|
|


>
>
>
|
>




|




>
>





<
|
|


>
>
|
>








|





|






|




>
>






<
|
|


>
>
>
>
|
>




|




>
>

|



<
|
|


>
>
>
|
>







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
	/*
	 * Check for mounted image.
	 */

	WriteLock();
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
		hPtr = Tcl_NextHashEntry(&search)) {
	    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 ((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_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 {





	    /*
	     * Fall back to read it as plain file which hopefully is a static
	     * tclsh or wish binary with proper zipfs infrastructure built in.
	     */


	    if (CopyImageFile(interp, imgName, out) != TCL_OK) {

		memset(passBuf, 0, sizeof(passBuf));
		Tcl_DecrRefCount(list);
		Tcl_Close(interp, out);
		return TCL_ERROR;
	    }










	}



















	/*
	 * 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_Close(interp, out);
		return TCL_ERROR;
	    }
	}
	memset(passBuf, 0, sizeof(passBuf));
	Tcl_Flush(out);
    }








    /*
     * Prepare the contents of the ZIP archive.
     */


    Tcl_InitHashTable(&fileHash, TCL_STRING_KEYS);
    if (mappingList == NULL && stripPrefix != NULL) {
	strip = TclGetStringFromObj(stripPrefix, &slen);


	if (!slen) {
	    strip = NULL;


	}

    }


    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, pathObj, name, out, pw, buf, sizeof(buf),
		&fileHash) != TCL_OK) {
	    goto done;
	}
    }

    /*
     * Construct the contents of the ZIP central directory.
     */

    directoryStartOffset = Tcl_Tell(out);
    count = 0;
    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;


















	hPtr = Tcl_FindHashEntry(&fileHash, name);
	if (!hPtr) {
	    continue;
	}
	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;

	}
	name = Tcl_DStringValue(&ds);
	len = Tcl_DStringLength(&ds);
	SerializeCentralDirectoryEntry(start, end, (unsigned char *) buf,



		z, 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);
    suffixStartOffset = Tcl_Tell(out);



    SerializeCentralDirectorySuffix(start, end, (unsigned char *) buf,
	    count, directoryStartOffset, suffixStartOffset);




    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_Close(interp, out);
    } else {
	Tcl_Close(interp, out);
    }
    Tcl_DecrRefCount(list);
    for (hPtr = Tcl_FirstHashEntry(&fileHash, &search); hPtr;
	    hPtr = Tcl_NextHashEntry(&search)) {
	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);
    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);
    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 ZipFSMkZipOrImg().
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See description of ZipFSMkZipOrImg().
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkZipObjCmd(
    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)) {

	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 ZipFSMkZipOrImg(interp, 0, objv[1], objv[2], NULL, NULL,
	    stripPrefix, password);
}

static int
ZipFSLMkZipObjCmd(
    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)) {

	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 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 ZipFSMkZipOrImg().
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See description of ZipFSMkZipOrImg().
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMkImgObjCmd(
    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)) {

	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 ZipFSMkZipOrImg(interp, 1, objv[1], objv[2], NULL,
	    originFile, stripPrefix, password);
}

static int
ZipFSLMkImgObjCmd(
    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?");
	return TCL_ERROR;
    }
    if (Tcl_IsSafe(interp)) {

	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 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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSCanonicalObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    char *mntpoint = NULL;
    char *filename = NULL;
    char *result;
    Tcl_DString dPath;

    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? filename ?inZipfs?");
	return TCL_ERROR;
    }

    Tcl_DStringInit(&dPath);
    if (objc == 2) {
	filename = TclGetString(objv[1]);
	result = CanonicalPath("", filename, &dPath, 1);
    } else if (objc == 3) {
	mntpoint = TclGetString(objv[1]);
	filename = TclGetString(objv[2]);
	result = CanonicalPath(mntpoint, filename, &dPath, 1);
    } else {
	int zipfs = 0;

	if (Tcl_GetBooleanFromObj(interp, objv[3], &zipfs)) {
	    return TCL_ERROR;
	}
	mntpoint = TclGetString(objv[1]);
	filename = TclGetString(objv[2]);
	result = CanonicalPath(mntpoint, filename, &dPath, zipfs);
    }




    Tcl_SetObjResult(interp, Tcl_NewStringObj(result, -1));
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSExistsObjCmd --







|




|
<
<
|

|
|


>
|
<
|
|
|
|
<
<

<
|
<


|
<
<

>
>
>
>
|







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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSCanonicalObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    const char *mntPoint = NULL;


    Tcl_DString dsPath, dsMount;

    if (objc < 2 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?mountpoint? filename");
	return TCL_ERROR;
    }

    Tcl_DStringInit(&dsPath);

    Tcl_DStringInit(&dsMount);

    if (objc == 2) {
	mntPoint = ZIPFS_VOLUME;


    } else {

	if (NormalizeMountPoint(interp, Tcl_GetString(objv[1]), &dsMount) != TCL_OK) {

	    return TCL_ERROR;
	}
	mntPoint = Tcl_DStringValue(&dsMount);


    }
    (void)MapPathToZipfs(interp,
			 mntPoint,
			 Tcl_GetString(objv[objc - 1]),
			 &dsPath);
    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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSExistsObjCmd(
    TCL_UNUSED(ClientData),
    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;





    Unlock();

    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(exists));
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSInfoObjCmd --
 *
 *	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_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    char *filename;
    ZipEntry *z;


    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));







    }


    Unlock();
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * 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_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);







    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);




	if ((n >= 2) && (strncmp(what, "-glob", n) == 0)) {


	    pattern = TclGetString(objv[2]);
	} else if ((n >= 2) && (strncmp(what, "-regexp", n) == 0)) {


	    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;
	}
    } else if (objc == 2) {
	pattern = TclGetString(objv[1]);
    }





    ReadLock();
    if (pattern) {
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
		hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
	    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);

	    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);

	    Tcl_ListObjAppendElement(interp, result,
		    Tcl_NewStringObj(z->name, -1));
	}
    }
    Unlock();
    return TCL_OK;







|






<






<
<
<
<

<
<
<
<



>
>
>
>
>











|















|






>


















>
>
>
>
>
>
>
|
>
>

|

|




















|









>
>
>
>
>
>






|
|
>
>
>
|
<
>
>

<
>
>




<
<
<
<
|




>
>
>
>
>




|









|









|







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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSExistsObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    char *filename;
    int exists;


    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "filename");
	return TCL_ERROR;
    }





    filename = TclGetString(objv[1]);





    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
 *	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(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 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(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) {
	int idx;

	if (Tcl_GetIndexFromObj(interp, objv[1], options, "option",
		0, &idx) != TCL_OK) {
	    return TCL_ERROR;
	}

	switch (idx) {
	case OPT_GLOB:
	    pattern = TclGetString(objv[2]);

	    break;
	case OPT_REGEXP:
	    regexp = Tcl_RegExpCompile(interp, TclGetString(objv[2]));
	    if (!regexp) {
		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);

	    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);

	    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);

	    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
 * 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 */












Tcl_Obj *
TclZipfs_TclLibrary(void)
{
    Tcl_Obj *vfsInitScript;
    int found;
#ifdef _WIN32

    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);
    }

    /*
     * 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);
    }

    /*
     * 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(_WIN32)
    hModule = (HMODULE)TclWinGetTclInstance();
    GetModuleFileNameW(hModule, wName, MAX_PATH);



    WideCharToMultiByte(CP_UTF8, 0, wName, -1, dllName, sizeof(dllName), NULL, NULL);

    if (ZipfsAppHookFindTclInit(dllName) == TCL_OK) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    }
#elif /* !_WIN32 && */ defined(CFG_RUNTIME_DLLFILE)
    if (ZipfsAppHookFindTclInit(
	    CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    }
#endif /* _WIN32 || CFG_RUNTIME_DLLFILE */

    /*
     * If we're configured to know about a ZIP archive we should use, do that.
     */

#ifdef CFG_RUNTIME_ZIPFILE
    if (ZipfsAppHookFindTclInit(
	    CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_ZIPFILE) == TCL_OK) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    }
    if (ZipfsAppHookFindTclInit(
	    CFG_RUNTIME_SCRDIR "/" CFG_RUNTIME_ZIPFILE) == TCL_OK) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    }

    if (ZipfsAppHookFindTclInit(CFG_RUNTIME_ZIPFILE) == TCL_OK) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    }
#endif /* CFG_RUNTIME_ZIPFILE */


    /*
     * 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 NULL;
}

/*
 *-------------------------------------------------------------------------
 *







<
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>






|
>











|













|







>
|


>
>
>

|
<
<
|
<
|
<
|

<
|
<
<
<
|
<
<
<
|
<
|
<
|

>
|
|

|
>







|







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
 * Side effects:
 *	May initialise the cache of where such library files are to be found.
 *	This cache is never cleared.
 *
 *-------------------------------------------------------------------------
 */


/* Utility routine to centralize housekeeping */
static Tcl_Obj *
ScriptLibrarySetup(
    const char *dirName)
{
    Tcl_Obj *libDirObj = Tcl_NewStringObj(dirName, -1);
    Tcl_Obj *subDirObj, *searchPathObj;

    TclNewLiteralStringObj(subDirObj, "encoding");
    Tcl_IncrRefCount(subDirObj);
    TclNewObj(searchPathObj);
    Tcl_ListObjAppendElement(NULL, searchPathObj,
	    Tcl_FSJoinToPath(libDirObj, 1, &subDirObj));
    Tcl_DecrRefCount(subDirObj);
    Tcl_IncrRefCount(searchPathObj);
    Tcl_SetEncodingSearchPath(searchPathObj);
    Tcl_DecrRefCount(searchPathObj);
    return libDirObj;
}

Tcl_Obj *
TclZipfs_TclLibrary(void)
{
    Tcl_Obj *vfsInitScript;
    int found;
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(STATIC_BUILD)
#   define LIBRARY_SIZE	    64
    HMODULE hModule;
    WCHAR wName[MAX_PATH + LIBRARY_SIZE];
    char dllName[(MAX_PATH + LIBRARY_SIZE) * 3];
#endif /* _WIN32 */

    /*
     * Use the cached value if that has been set; we don't want to repeat the
     * searching and mounting.
     */

    if (zipfs_literal_tcl_library) {
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }

    /*
     * Look for the library file system within the executable.
     */

    vfsInitScript = Tcl_NewStringObj(ZIPFS_APP_MOUNT "/tcl_library/init.tcl",
	    -1);
    Tcl_IncrRefCount(vfsInitScript);
    found = Tcl_FSAccess(vfsInitScript, F_OK);
    Tcl_DecrRefCount(vfsInitScript);
    if (found == TCL_OK) {
	zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library";
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }

    /*
     * Look for the library file system within the DLL/shared library.  Note
     * that we must mount the zip file and dll before releasing to search.
     */

#if !defined(STATIC_BUILD)
#if defined(_WIN32) || defined(__CYGWIN__)
    hModule = (HMODULE)TclWinGetTclInstance();
    GetModuleFileNameW(hModule, wName, MAX_PATH);
#ifdef __CYGWIN__
    cygwin_conv_path(3, wName, dllName, sizeof(dllName));
#else
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, dllName, sizeof(dllName), NULL, NULL);
#endif




    if (ZipfsAppHookFindTclInit(dllName) == TCL_OK) {

	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }

#elif !defined(NO_DLFCN_H)



    Dl_info dlinfo;



    if (dladdr((const void *)TclZipfs_TclLibrary, &dlinfo) && (dlinfo.dli_fname != NULL)

	    && (ZipfsAppHookFindTclInit(dlinfo.dli_fname) == TCL_OK)) {

	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
#else
    if (ZipfsAppHookFindTclInit(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) {
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
#endif /* _WIN32 */
#endif /* !defined(STATIC_BUILD) */

    /*
     * If anything set the cache (but subsequently failed) go with that
     * anyway.
     */

    if (zipfs_literal_tcl_library) {
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
    return NULL;
}

/*
 *-------------------------------------------------------------------------
 *
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
 *	This cache is never cleared.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSTclLibraryObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *)) /*objv*/
{
    if (!Tcl_IsSafe(interp)) {
	Tcl_Obj *pResult = TclZipfs_TclLibrary();








|







4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
 *	This cache is never cleared.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSTclLibraryObjCmd(
    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

static int
ZipChannelClose(
    void *instanceData,
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    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) {




	ZipEntry *z = info->zipEntryPtr;


	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;
	} else {
	    Tcl_Free(info->ubuf);
	}
    }
    WriteLock();
    info->zipFilePtr->numOpen--;
    Unlock();







    Tcl_Free(info);
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *







|





<
<
<
<




|
>
>
>
>

>
>
|
>
>
>
>
>
|
>
>
>
|
>
|
|
|
|
|
>
|
|
|
|
|
|
<
<
|
<
<


>
>
>
>
>
>
>







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

static int
ZipChannelClose(
    void *instanceData,
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    ZipChannel *info = (ZipChannel *) instanceData;

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
	return EINVAL;
    }





    if (info->isEncrypted) {
	info->isEncrypted = 0;
	memset(info->keys, 0, sizeof(info->keys));
    }
    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;
	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;


    }


    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
ZipChannelRead(
    void *instanceData,
    char *buf,
    int toRead,
    int *errloc)
{
    ZipChannel *info = (ZipChannel *) instanceData;
    unsigned long 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->zipFilePtr->baseOffset;
	}
	if (toRead == 0) {
	    return 0;
	}
	memcpy(buf, info->zipFilePtr->data, toRead);
	info->numRead = nextpos;
	*errloc = 0;
	return toRead;
    }
    if (info->isDirectory) {
	*errloc = EISDIR;
	return -1;
    }
    nextpos = info->numRead + toRead;
    if (nextpos > info->numBytes) {
	toRead = info->numBytes - info->numRead;
	nextpos = info->numBytes;
    }
    if (toRead == 0) {
	return 0;
    }
    if (info->isEncrypted) {
	int i;





	for (i = 0; i < toRead; i++) {
	    int ch = info->ubuf[i + info->numRead];

	    buf[i] = zdecode(info->keys, crc32tab, ch);
	}
    } else {
	memcpy(buf, info->ubuf + info->numRead, toRead);
    }
    info->numRead = nextpos;
    *errloc = 0;
    return toRead;
}

/*
 *-------------------------------------------------------------------------
 *







|







|
|
|






|







|

|







|
>
>
>
>

|




|

|







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
ZipChannelRead(
    void *instanceData,
    char *buf,
    int toRead,
    int *errloc)
{
    ZipChannel *info = (ZipChannel *) instanceData;
    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->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->cursor = nextpos;
	*errloc = 0;
	return toRead;
    }
    if (info->isDirectory) {
	*errloc = EISDIR;
	return -1;
    }
    nextpos = info->cursor + toRead;
    if (nextpos > info->numBytes) {
	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->cursor];

	    buf[i] = zdecode(info->keys, crc32tab, ch);
	}
    } else {
	memcpy(buf, info->ubuf + info->cursor, toRead);
    }
    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
    const char *buf,
    int toWrite,
    int *errloc)
{
    ZipChannel *info = (ZipChannel *) instanceData;
    unsigned long nextpos;

    if (!info->isWriting) {
	*errloc = EINVAL;
	return -1;
    }
    nextpos = info->numRead + toWrite;


    if (nextpos > info->maxWrite) {
	toWrite = info->maxWrite - info->numRead;
	nextpos = info->maxWrite;
    }
    if (toWrite == 0) {

	return 0;
    }
































    memcpy(info->ubuf + info->numRead, buf, toWrite);
    info->numRead = nextpos;
    if (info->numRead > info->numBytes) {
	info->numBytes = info->numRead;
    }
    *errloc = 0;
    return toWrite;
}

/*
 *-------------------------------------------------------------------------







|



|
>
>
|
|
|
|

>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|







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
    const char *buf,
    int toWrite,
    int *errloc)
{
    ZipChannel *info = (ZipChannel *) instanceData;
    unsigned long nextpos;

    if (!ZipChannelWritable(info)) {
	*errloc = EINVAL;
	return -1;
    }

    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->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
 *
 * Side effects:
 *	File pointer is repositioned according to offset and mode.
 *
 *-------------------------------------------------------------------------
 */

static Tcl_WideInt
ZipChannelWideSeek(
    void *instanceData,
    Tcl_WideInt offset,
    int mode,
    int *errloc)
{
    ZipChannel *info = (ZipChannel *) instanceData;
    size_t end;

    if (!info->isWriting && (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;
	break;
    case SEEK_END:
	offset += end;
	break;
    case SEEK_SET:
	break;
    default:
	*errloc = EINVAL;
	return -1;
    }
    if (offset < 0) {
	*errloc = EINVAL;
	return -1;
    }
    if (info->isWriting) {
	if ((size_t) offset > info->maxWrite) {
	    *errloc = EINVAL;
	    return -1;
	}
	if ((size_t) offset > info->numBytes) {
	    info->numBytes = offset;
	}
    } else if ((size_t) offset > end) {
	*errloc = EINVAL;
	return -1;
    }
    info->numRead = (size_t) offset;
    return info->numRead;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipChannelWatchChannel --
 *







|


|




|

|













|










|



|
|



|


|



|
|







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
 *
 * Side effects:
 *	File pointer is repositioned according to offset and mode.
 *
 *-------------------------------------------------------------------------
 */

static long long
ZipChannelWideSeek(
    void *instanceData,
    long long offset,
    int mode,
    int *errloc)
{
    ZipChannel *info = (ZipChannel *) instanceData;
    Tcl_Size end;

    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->cursor;
	break;
    case SEEK_END:
	offset += end;
	break;
    case SEEK_SET:
	break;
    default:
	*errloc = EINVAL;
	return -1;
    }
    if (offset < 0 || offset > TCL_SIZE_MAX) {
	*errloc = EINVAL;
	return -1;
    }
    if (ZipChannelWritable(info)) {
	if (offset > info->maxWrite) {
	    *errloc = EINVAL;
	    return -1;
	}
	if (offset > info->numBytes) {
	    info->numBytes = offset;
	}
    } else if (offset > end) {
	*errloc = EINVAL;
	return -1;
    }
    info->cursor = (Tcl_Size) offset;
    return info->cursor;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipChannelWatchChannel --
 *
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static void
ZipChannelWatchChannel(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(int) /*mask*/)
{
    return;
}

/*
 *-------------------------------------------------------------------------







|







4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static void
ZipChannelWatchChannel(
    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
3903
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipChannelGetFile(
    TCL_UNUSED(ClientData),
    TCL_UNUSED(int) /*direction*/,
    TCL_UNUSED(ClientData *) /*handlePtr*/)
{
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipChannelOpen --
 *
 *	This function opens a Tcl_Channel on a file from a mounted ZIP archive
 *	according to given open mode.
 *
 * 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,
    TCL_UNUSED(int) /*permissions*/)
{
    ZipEntry *z;
    ZipChannel *info;
    int i, ch, trunc, wr, flags = 0;
    char cname[128];


    if ((mode & O_APPEND)


	    || ((ZipFS.wrmax <= 0) && (mode & (O_WRONLY | O_RDWR)))) {

	if (interp) {
	    Tcl_SetObjResult(interp,





		    Tcl_NewStringObj("unsupported open mode", -1));

	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "BAD_MODE", NULL);





	}
	return NULL;
    }





    WriteLock();
    z = ZipFSLookup(filename);
    if (!z) {





















	Tcl_SetErrno(ENOENT);
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "file not found \"%s\": %s", filename,
		    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);
	}
	goto error;
    }
    if (wr && z->isDirectory) {


	ZIPFS_ERROR(interp, "unsupported file type");
	if (interp) {
	    Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "FILE_TYPE", NULL);
	}

	goto error;

    }
    if (!trunc) {

	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);
	    }
	    goto error;
	} else if (wr && !z->data && (z->numBytes > ZipFS.wrmax)) {
	    ZIPFS_ERROR(interp, "file too large");
	    if (interp) {
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "FILE_SIZE", NULL);
	    }
	    goto error;
	}
    } else {
	flags = TCL_WRITABLE;
    }
    info = (ZipChannel *)Tcl_AttemptAlloc(sizeof(ZipChannel));

    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;
	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);
	    }

	    Tcl_Free(info);
	    ZIPFS_ERROR(interp, "out of memory");
	    if (interp) {
		Tcl_SetErrorCode(interp, "TCL", "MALLOC", NULL);
	    }
	    goto error;
	}
	memset(info->ubuf, 0, info->maxWrite);
	if (trunc) {
	    info->numBytes = 0;
	} else if (z->data) {
	    size_t j = z->numBytes;

	    if (j > info->maxWrite) {
		j = info->maxWrite;
	    }
	    memcpy(info->ubuf, z->data, j);
	    info->numBytes = j;
	} else {
	    unsigned char *zbuf = z->zipFilePtr->data + z->offset;

	    if (z->isEncrypted) {
		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, info->keys, crc32tab);
		memset(passBuf, 0, sizeof(passBuf));
		for (i = 0; i < 12; i++) {
		    ch = info->ubuf[i];
		    zdecode(info->keys, crc32tab, ch);
		}
		zbuf += i;
	    }
	    if (z->compressMethod == ZIP_COMPMETH_DEFLATED) {
		z_stream stream;
		int err;
		unsigned char *cbuf = NULL;

		memset(&stream, 0, sizeof(z_stream));
		stream.zalloc = Z_NULL;
		stream.zfree = Z_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++) {
			ch = info->ubuf[j];
			cbuf[j] = zdecode(info->keys, crc32tab, ch);
		    }
		    stream.next_in = cbuf;
		} else {
		    stream.next_in = zbuf;
		}
		stream.next_out = info->ubuf;
		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)
			|| ((err == Z_OK) && (stream.avail_in == 0))) {
		    if (cbuf) {
			memset(info->keys, 0, sizeof(info->keys));
			Tcl_Free(cbuf);
		    }
		    goto wrapchan;
		}
	    cerror0:
		if (cbuf) {
		    memset(info->keys, 0, sizeof(info->keys));
		    Tcl_Free(cbuf);
		}
		if (info->ubuf) {
		    Tcl_Free(info->ubuf);
		}
		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++) {
		    ch = zbuf[i];
		    info->ubuf[i] = zdecode(info->keys, crc32tab, ch);
		}
	    } else {
		memcpy(info->ubuf, zbuf, z->numBytes);
	    }
	    memset(info->keys, 0, sizeof(info->keys));
	    goto wrapchan;
	}
    } else if (z->data) {
	flags |= TCL_READABLE;
	info->isWriting = 0;
	info->iscompr = 0;
	info->isDirectory = 0;
	info->isEncrypted = 0;
	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);
	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];
		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];
		zdecode(info->keys, crc32tab, ch);
	    }
	    info->ubuf += i;

	}
	if (info->iscompr) {
	    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) {
		    info->ubuf = NULL;
		    goto merror;
		}
		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;



	    }
	    stream.next_out = info->ubuf = (unsigned char *)Tcl_AttemptAlloc(info->numBytes);
	    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;
	    if (inflateInit2(&stream, -15) != Z_OK) {
		goto cerror;
	    }
	    err = inflate(&stream, Z_SYNC_FLUSH);
	    inflateEnd(&stream);
	    if ((err == Z_STREAM_END)
		    || ((err == Z_OK) && (stream.avail_in == 0))) {
		if (ubuf) {

		    info->isEncrypted = 0;
		    memset(info->keys, 0, sizeof(info->keys));
		    Tcl_Free(ubuf);
		}
		goto wrapchan;
	    }
	cerror:
	    if (ubuf) {
		info->isEncrypted = 0;
		memset(info->keys, 0, sizeof(info->keys));
		Tcl_Free(ubuf);
	    }
	    if (info->ubuf) {
		Tcl_Free(info->ubuf);

	    }
	    Tcl_Free(info);
	    ZIPFS_ERROR(interp, "decompression error");
	    if (interp) {
		Tcl_SetErrorCode(interp, "TCL", "ZIPFS", "CORRUPT", NULL);
	    }
	    goto error;
	} else if (info->isEncrypted) {
	    unsigned char *ubuf = NULL;
	    size_t j, len;

	    /*
	     * Decode encrypted but uncompressed file, since we support
	     * Tcl_Seek() on it, and it can be randomly accessed later.

	     */

	    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;
	    }
	    for (j = 0; j < len; j++) {
		ch = info->ubuf[j];
		ubuf[j] = zdecode(info->keys, crc32tab, ch);
	    }
	    info->ubuf = ubuf;
	    info->isEncrypted = 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;
}

























































































































































































































































































































































/*
 *-------------------------------------------------------------------------
 *
 * ZipEntryStat --
 *
 *	This function implements the ZIP filesystem specific version of the







|

|










|













|
|
<



|


>
|
>
>
|
>

|
>
>
>
>
>
|
>
|
>
>
>
>
>



>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


|




<
<



<
|
<


|
>
>
|
|
<

>
|
>
|
|
>

>
>
|
>
|
>
|
|
|
<
|
|
|
<
<


<
<

|
>

<
<
<
<




<

<
|
<
<
<
<
<
<
<
<
<
|
>

<
<
<
<


<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
>
|

<
<
<
<
<
<
<
<
<
<
>
|
|
<
<
<
|
<
|
<
<
<
<
<
|
>

<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
|
>
|
<
<
<
|
>
>
>

<
<
<
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
>
|
<
|
<
<
<
<
<
|
<
<

<
|
>
|
<
<
<
<
|
<
<
<
<

|
<
<
>
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipChannelGetFile(
    TCL_UNUSED(void *),
    TCL_UNUSED(int) /*direction*/,
    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 (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,		/* What are we opening. */
    int mode)			/* O_WRONLY O_RDWR O_TRUNC flags */

{
    ZipEntry *z;
    ZipChannel *info;
    int flags = 0;
    char cname[128];

    int wr = (mode & (O_WRONLY | O_RDWR)) != 0;

    /* Check for unsupported modes. */

    if ((ZipFS.wrmax <= 0) && wr) {
	Tcl_SetErrno(EACCES);
	if (interp) {
	    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(EISDIR);
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "unsupported file type: %s",
		    Tcl_PosixError(interp)));
	}
	goto error;
    }


    if ((z->compressMethod != ZIP_COMPMETH_STORED)
	    && (z->compressMethod != ZIP_COMPMETH_DEFLATED)) {
	ZIPFS_ERROR(interp, "unsupported compression method");

	ZIPFS_ERROR_CODE(interp, "COMP_METHOD");

	goto error;
    }
    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;

	}
	flags = TCL_WRITABLE;
	if (mode & O_RDWR) {
	    flags |= TCL_READABLE;
	}
    } else {
	/* Read-only */
	flags |= TCL_READABLE;
    }

    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;
	}

	if (z->zipFilePtr->passBuf[0] == 0) {
	    ZIPFS_ERROR(interp, "decryption failed - no password provided");
	    ZIPFS_ERROR_CODE(interp, "DECRYPT");


	    goto error;
	}


    }

    info = AllocateZipChannel(interp);
    if (!info) {




	goto error;
    }
    info->zipFilePtr = z->zipFilePtr;
    info->zipEntryPtr = z;

    if (wr) {

	/* Set up a writable channel. */










	if (InitWritableChannel(interp, info, z, mode) == TCL_ERROR) {
	    Tcl_Free(info);




	    goto error;
	}



    } else if (z->data) {

	/* Set up a readable channel for direct data. */

































































































	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 (z->crc32) {
	if (!(z->flags & ZE_F_CRC_COMPARED)) {
	    int crc = crc32(0, NULL, info->numBytes);



	    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->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;


	    }

	    Tcl_Free(info);
	    goto error;
	}




    }





    /*


     * Wrap the ZipChannel into a Tcl_Channel.
     */





















    snprintf(cname, sizeof(cname), "zipfs_%" TCL_Z_MODIFIER "x_%d", z->offset,
	    ZipFS.idCount++);
    z->zipFilePtr->numOpen++;
    Unlock();
    return Tcl_CreateChannel(&ZipChannelType, cname, info, flags);

  error:
    Unlock();
    return NULL;
}

/*
 *-------------------------------------------------------------------------
 *
 * InitWritableChannel --
 *
 *	Assistant for ZipChannelOpen() that sets up a writable channel. It's
 *	up to the caller to actually register the channel.
 *
 * Returns:
 *	Tcl result code.
 *
 * Side effects:
 *	Allocates memory for the implementation of the channel. Writes to the
 *	interpreter's result on error.
 *
 *-------------------------------------------------------------------------
 */

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 */
{
    int i, ch;
    unsigned char *cbuf = NULL;

    /*
     * Set up a writable channel.
     */

    info->mode = mode;
    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) {
	goto memoryError;
    }

    if (z->isEncrypted) {
	assert(z->numCompressedBytes >= ZIP_CRYPT_HDR_LEN); /* caller should have checked*/
	if (DecodeCryptHeader(interp, z, info->keys,
		z->zipFilePtr->data + z->offset) != TCL_OK) {
	    goto error_cleanup;
	}
    }

    if (mode & O_TRUNC) {
	/*
	 * Truncate; nothing there.
	 */

	info->numBytes = 0;
	z->crc32 = 0; /* Truncated, CRC no longer applicable */
    } else if (z->data) {
	/*
	 * Already got uncompressed data.
	 */
	assert(info->ubufSize >= z->numBytes);
	memcpy(info->ubuf, z->data, z->numBytes);
	info->numBytes = z->numBytes;
    } else {
	/*
	 * Need to uncompress the existing data.
	 */

	unsigned char *zbuf = z->zipFilePtr->data + z->offset;

	if (z->isEncrypted) {
	    zbuf += ZIP_CRYPT_HDR_LEN;
	}

	if (z->compressMethod == ZIP_COMPMETH_DEFLATED) {
	    z_stream stream;
	    int err;

	    memset(&stream, 0, sizeof(z_stream));
	    stream.zalloc = Z_NULL;
	    stream.zfree = Z_NULL;
	    stream.opaque = Z_NULL;
	    stream.avail_in = z->numCompressedBytes;
	    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) {
		    goto memoryError;
		}
		for (j = 0; j < stream.avail_in; j++) {
		    ch = zbuf[j];
		    cbuf[j] = zdecode(info->keys, crc32tab, ch);
		}
		stream.next_in = cbuf;
	    } else {
		stream.next_in = zbuf;
	    }
	    stream.next_out = info->ubuf;
	    stream.avail_out = info->ubufSize;
	    if (inflateInit2(&stream, -15) != Z_OK) {
		goto corruptionError;
	    }
	    err = inflate(&stream, Z_SYNC_FLUSH);
	    inflateEnd(&stream);
	    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;
	    }
	    info->numBytes = z->numBytes;
	    if (cbuf) {
		Tcl_Free(cbuf);
	    }
	} 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;
	    assert(len <= info->ubufSize);
	    for (i = 0; i < len; i++) {
		ch = zbuf[i];
		info->ubuf[i] = zdecode(info->keys, crc32tab, ch);
	    }
	    info->numBytes = len;
	} else {
	    /*
	     * Simple stored data. Copy into our working buffer.
	     */
	    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. */
{
    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 < 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 = 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;
    }

    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipEntryStat --
 *
 *	This function implements the ZIP filesystem specific version of the
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

static int
ZipEntryStat(
    char *path,
    Tcl_StatBuf *buf)
{
    ZipEntry *z;
    int ret = -1;

    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;











    }
    Unlock();
    return ret;
}

/*
 *-------------------------------------------------------------------------







|















>
>
>
>
>
>
>
>
>
>
>







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

static int
ZipEntryStat(
    char *path,
    Tcl_StatBuf *buf)
{
    ZipEntry *z;
    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
 */

static int
ZipEntryAccess(
    char *path,
    int mode)
{
    ZipEntry *z;

    if (mode & 3) {
	return -1;
    }

    ReadLock();

    z = ZipFSLookup(path);














    Unlock();
    return (z ? 0 : -1);
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSOpenFileChannelProc --
 *



 * Results:

 *
 * Side effects:

 *
 *-------------------------------------------------------------------------
 */

static Tcl_Channel
ZipFSOpenFileChannelProc(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Obj *pathPtr,
    int mode,
    int permissions)
{
    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return NULL;
    }

    return ZipChannelOpen(interp, TclGetString(pathPtr), mode,
	    permissions);
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSStatProc --
 *
 *	This function implements the ZIP filesystem specific version of the
 *	library version of stat.







<
<
|


>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|

|





>
>
>

>


>









|





>
|
<

|







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
 */

static int
ZipEntryAccess(
    char *path,
    int mode)
{


    if (mode & X_OK) {
	return -1;
    }

    ReadLock();
    int access;
    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 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,
    TCL_UNUSED(int) /* permissions */)
{
    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return NULL;
    }

    return ZipChannelOpen(interp, Tcl_GetString(pathPtr), mode);

}

/*
 *-------------------------------------------------------------------------
 *
 * 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
 */

static int
ZipFSStatProc(
    Tcl_Obj *pathPtr,
    Tcl_StatBuf *buf)
{

    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return -1;
    }
    return ZipEntryStat(TclGetString(pathPtr), buf);
}








<







5401
5402
5403
5404
5405
5406
5407

5408
5409
5410
5411
5412
5413
5414
 */

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
{
    return Tcl_NewStringObj("/", -1);
}

/*
 *-------------------------------------------------------------------------
 *
































 * 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).
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMatchInDirectoryProc(
    TCL_UNUSED(Tcl_Interp *),
    Tcl_Obj *result,
    Tcl_Obj *pathPtr,
    const char *pattern,
    Tcl_GlobTypeData *types)
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    Tcl_Obj *normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    int scnt, l, dirOnly = -1, strip = 0;
    size_t len, prefixLen;
    char *pat, *prefix, *path;
    Tcl_DString dsPref;




    if (!normPathPtr) {
	return -1;
    }
    if (types) {

















	dirOnly = (types->type & TCL_GLOB_TYPE_DIR) == TCL_GLOB_TYPE_DIR;
    }

    /*
     * 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;
    } else {

	strip = len + 1;


    }

    if (prefix) {
	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 = "*";
	}
	for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
		hPtr = Tcl_NextHashEntry(&search)) {
	    ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr);


	    if (zf->mountPointLen == 0) {
		ZipEntry *z;

		for (z = zf->topEnts; z; z = z->tnext) {


		    size_t lenz = strlen(z->name);

		    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));
			}


		    }
		}


	    } else if ((zf->mountPointLen > len + 1)
		    && (strncmp(zf->mountPoint, path, len) == 0)
		    && (zf->mountPoint[len] == '/')
		    && (CountSlashes(zf->mountPoint) == l)
		    && Tcl_StringCaseMatch(zf->mountPoint + len + 1,

			    pattern, 0)) {


		if (prefix) {
		    Tcl_DStringAppend(&dsPref, zf->mountPoint,
			    zf->mountPointLen);
		    Tcl_ListObjAppendElement(NULL, result,
			    Tcl_NewStringObj(Tcl_DStringValue(&dsPref),
				    Tcl_DStringLength(&dsPref)));
		    Tcl_DStringSetLength(&dsPref, prefixLen);
		} else {
		    Tcl_ListObjAppendElement(NULL, result,
			    Tcl_NewStringObj(zf->mountPoint,
				    zf->mountPointLen));
		}
	    }
	}
	goto end;
    }



    if (!pattern || (pattern[0] == '\0')) {
	hPtr = Tcl_FindHashEntry(&ZipFS.fileHash, path);
	if (hPtr) {
	    ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr);

	    if ((dirOnly < 0) || (!dirOnly && !z->isDirectory)
		    || (dirOnly && z->isDirectory)) {
		if (prefix) {
		    Tcl_DStringAppend(&dsPref, z->name, -1);
		    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, -1));
		}
	    }
	}
	goto end;
    }






    l = strlen(pattern);
    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);








    for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search);
	    hPtr; hPtr = Tcl_NextHashEntry(&search)) {
	ZipEntry *z = (ZipEntry *)Tcl_GetHashValue(hPtr);


	if ((dirOnly >= 0) && ((dirOnly && !z->isDirectory)
		|| (!dirOnly && z->isDirectory))) {


























	    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);
	    } else {
		Tcl_ListObjAppendElement(NULL, result,
			Tcl_NewStringObj(z->name + strip, -1));
	    }
	}
    }

    Tcl_Free(pat);

  end:
    Unlock();
    Tcl_DStringFree(&dsPref);
    return TCL_OK;
}




























































































/*
 *-------------------------------------------------------------------------
 *
 * ZipFSPathInFilesystemProc --
 *
 *	This function determines if the given path object is in the ZIP







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|









|
|
|
|
|

<
<

|
|

|
>
>
>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|















<
<

|

>
|
>
>
|
>
|

<

<
<
<
<
<
<
<
<
<
<
|
|
<
|
|

>
|
|

<
>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
>
>
|
<
>
>
|
<
|
|
|
>
|
>
>
|
<
<
<
|
|
<
<
|
<
<
|
<
<
|
<
|
>
>
|
<
<
<
|
<
<
|
<
|
<
<
<
>
|
<
<
|
|
|
|
|
>
>
>
>
>


|










>
>
>
>
>
>
>
>
|
|
|

>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
<
<
>
|
|
|
>
>
>
>
|
>
|
<
<
<



>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
{
    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 result (which must be a valid object).
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSMatchInDirectoryProc(
    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_Obj *normPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    int scnt, l;
    Tcl_Size prefixLen, len, strip = 0;
    char *pat, *prefix, *path;
    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 {
	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);


    if (strcmp(prefix, path) == 0) {
	prefixBuf = NULL;
    } else {
	/*
	 * 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);

	prefix = Tcl_DStringValue(&dsPref);










	prefixBuf = &dsPref;
    }


    ReadLock();

    /*
     * Are we globbing the mount points?
     */


    if (wanted & TCL_GLOB_TYPE_MOUNT) {
	ZipFSMatchMountPoints(result, normPathPtr, pattern, prefixBuf);
	goto end;
    }















    /* Should not reach here unless at least one of DIR or FILE is set */
    assert(wanted & (TCL_GLOB_TYPE_DIR | TCL_GLOB_TYPE_FILE));


    /* Does the path exist in the hash table? */
    z = ZipFSLookup(path);
    if (z) {

	/*
	 * 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)) ||



		    (wanted == TCL_GLOB_TYPE_DIR && z->isDirectory) ||
		    (wanted == TCL_GLOB_TYPE_FILE && !z->isDirectory)) {


		Tcl_ListObjAppendElement(NULL, result, pathPtr);


	    }


	    goto end;

	}
    } else {
	/* Not in the hash table but could be an intermediate dir in a mount */
	if (!pattern || (pattern[0] == '\0')) {



	    /* TODO - can't seem to get to this code from script for tests. */


	    if ((wanted & TCL_GLOB_TYPE_DIR) && ContainsMountPoint(path, len)) {

		Tcl_ListObjAppendElement(NULL, result, pathPtr);



	    }
	    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);
    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)) {
	    z = (ZipEntry *)Tcl_GetHashValue(hPtr);

	    if ((wanted == (TCL_GLOB_TYPE_DIR | TCL_GLOB_TYPE_FILE)) ||
		    (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;
		}


		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);



	    }
	}
    }
    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
4354
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSPathInFilesystemProc(
    Tcl_Obj *pathPtr,
    TCL_UNUSED(ClientData *))
{
    Tcl_HashEntry *hPtr;
    Tcl_HashSearch search;
    int ret = -1;
    size_t len;
    char *path;

    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return -1;
    }

    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;
    }

    for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr;
	    hPtr = Tcl_NextHashEntry(&search)) {
	ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr);

	if (zf->mountPointLen == 0) {
	    ZipEntry *z;

	    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;
		    goto endloop;
		}
	    }
	} else if ((len >= zf->mountPointLen) &&
		(strncmp(path, zf->mountPoint, zf->mountPointLen) == 0)) {
	    ret = TCL_OK;
	    break;
	}
    }

  endloop:
    Unlock();
    return ret;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSListVolumesProc --
 *







|

<
<
<
|






<

<
<
|
|
<
<
<
<
<
<
|
<
<
<
|
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<







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
 *
 *-------------------------------------------------------------------------
 */

static int
ZipFSPathInFilesystemProc(
    Tcl_Obj *pathPtr,
    TCL_UNUSED(void **))
{



    Tcl_Size len;
    char *path;

    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return -1;
    }

    path = TclGetStringFromObj(pathPtr, &len);



    /*






     * Claim any path under ZIPFS_VOLUME as ours. This is both a necessary



     * and sufficient condition as zipfs mounts at arbitrary paths are


     * not permitted (unlike Androwish).


     */











    return strncmp(path, ZIPFS_VOLUME, ZIPFS_VOLUME_LEN) ? -1 : TCL_OK;



}

/*
 *-------------------------------------------------------------------------
 *
 * 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
 *	An array of strings
 *
 * Side effects:
 *	None.
 *
 *-------------------------------------------------------------------------
 */











static const char *const *
ZipFSFileAttrStringsProc(
    TCL_UNUSED(Tcl_Obj *) /*pathPtr*/,
    TCL_UNUSED(Tcl_Obj **) /*objPtrRef*/)
{




    static const char *const attrs[] = {
	"-uncompsize",
	"-compsize",
	"-offset",
	"-mount",
	"-archive",
	"-permissions",

	NULL,
    };

    return attrs;
}

/*







>
>
>
>
>
>
>
>
>
>






>
>
>
>







>







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
 *	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
static int
ZipFSFileAttrsGetProc(
    Tcl_Interp *interp,		/* Current interpreter. */
    int index,
    Tcl_Obj *pathPtr,
    Tcl_Obj **objPtrRef)
{

    int ret = TCL_OK;
    char *path;
    ZipEntry *z;

    pathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
    if (!pathPtr) {
	return -1;
    }
    path = TclGetString(pathPtr);
    ReadLock();
    z = ZipFSLookup(path);
    if (!z) {
	Tcl_SetErrno(ENOENT);
	ZIPFS_POSIX_ERROR(interp, "file not found");
	ret = TCL_ERROR;
	goto done;
    }

    switch (index) {
    case 0:
	TclNewIntObj(*objPtrRef, z->numBytes);
	break;
    case 1:
	TclNewIntObj(*objPtrRef, z->numCompressedBytes);
	break;
    case 2:
	TclNewIntObj(*objPtrRef, z->offset);
	break;
    case 3:

	*objPtrRef = Tcl_NewStringObj(z->zipFilePtr->mountPoint,
		z->zipFilePtr->mountPointLen);



	break;
    case 4:
	*objPtrRef = Tcl_NewStringObj(z->zipFilePtr->name, -1);
	break;
    case 5:
	*objPtrRef = Tcl_NewStringObj("0o555", -1);
	break;



    default:
	ZIPFS_ERROR(interp, "unknown attribute");

	ret = TCL_ERROR;
    }

  done:
    Unlock();
    return ret;
}







>








|


|





>

|
|

|
|

|
|

|
>
|
|
>
>
>

|
|

|


>
>
>


>







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
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 = TclGetStringFromObj(pathPtr, &len);
    ReadLock();
    z = ZipFSLookup(path);
    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 ZIP_ATTR_UNCOMPSIZE:
	TclNewIntObj(*objPtrRef, z ? z->numBytes : 0);
	break;
    case ZIP_ATTR_COMPSIZE:
	TclNewIntObj(*objPtrRef, z ? z->numCompressedBytes : 0);
	break;
    case ZIP_ATTR_OFFSET:
	TclNewIntObj(*objPtrRef, z ? z->offset : 0);
	break;
    case ZIP_ATTR_MOUNT:
	if (z) {
	    *objPtrRef = Tcl_NewStringObj(z->zipFilePtr->mountPoint,
					  z->zipFilePtr->mountPointLen);
	} else {
	    *objPtrRef = Tcl_NewStringObj("", 0);
	}
	break;
    case ZIP_ATTR_ARCHIVE:
	*objPtrRef = Tcl_NewStringObj(z ? z->zipFilePtr->name : "", -1);
	break;
    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
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);
    }
    return TCL_ERROR;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSFilesystemPathTypeProc --







<
|
|
<







6022
6023
6024
6025
6026
6027
6028

6029
6030

6031
6032
6033
6034
6035
6036
6037
static int
ZipFSFileAttrsSetProc(
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*index*/,
    TCL_UNUSED(Tcl_Obj *) /*pathPtr*/,
    TCL_UNUSED(Tcl_Obj *) /*objPtr*/)
{

    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
	 * [file dirname [info nameofexecutable]] is equal to [info
	 * nameofexecutable] due to VFS effects.
	 */

	if (execName) {
	    const char *p = strrchr(execName, '/');

	    if (p > execName + 1) {
		--p;
		objs[0] = Tcl_NewStringObj(execName, p - execName);
	    }
	}
	if (!objs[0]) {
	    objs[0] = TclPathPart(interp, TclGetObjNameOfExecutable(),
		    TCL_PATH_DIRNAME);







|







6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
	 * [file dirname [info nameofexecutable]] is equal to [info
	 * nameofexecutable] due to VFS effects.
	 */

	if (execName) {
	    const char *p = strrchr(execName, '/');

	    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
    if (objs[0]) {
	Tcl_DecrRefCount(objs[0]);
    }
    if (objs[1]) {
	Tcl_DecrRefCount(objs[1]);
    }

    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) {







|
>







6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
    if (objs[0]) {
	Tcl_DecrRefCount(objs[0]);
    }
    if (objs[1]) {
	Tcl_DecrRefCount(objs[1]);
    }

    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) {
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
    }
    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);



	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));
	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 */
}




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)) {
	/* 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);







|
>
|
|
>
>
>












|




|




>
>
>










|







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
    }
    Unlock();

    if (interp) {
	Tcl_Command ensemble;
	Tcl_Obj *mapObj;

	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));
	Tcl_CreateObjCommand(interp, "::tcl::zipfs::tcl_library_init",
		ZipFSTclLibraryObjCmd, NULL, NULL);
	Tcl_PkgProvide(interp, "tcl::zipfs", "2.0");
    }
    return TCL_OK;
#else /* !HAVE_ZLIB */
    ZIPFS_ERROR(interp, "no zlib available");
    ZIPFS_ERROR_CODE(interp, "NO_ZLIB");
    return TCL_ERROR;
#endif /* HAVE_ZLIB */
}

#ifdef 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, 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
    if (found == 0) {
	zipfs_literal_tcl_library = ZIPFS_ZIP_MOUNT "/tcl_library";
	return TCL_OK;
    }

    return TCL_ERROR;
}



















static void
ZipfsExitHandler(
    ClientData clientData)
{










    ZipFile *zf = (ZipFile *)clientData;





    if (TCL_OK != TclZipfs_Unmount(NULL, zf->mountPoint)) {
	Tcl_Panic("tried to unmount busy filesystem");





    }



}

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_AppHook --
 *
 *	Performs the argument munging for the shell
 *
 *-------------------------------------------------------------------------
 */

int
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;


#ifdef _WIN32
    Tcl_FindExecutable(NULL);
#else
    Tcl_FindExecutable((*argvPtr)[0]);
#endif
    archive = (char *) 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)) {
	int found;
	Tcl_Obj *vfsInitScript;

	TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
	Tcl_IncrRefCount(vfsInitScript);
	if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
	    /*







>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
<

>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
|
|
>
>
>
>
>

>
>
>












|












|
>


|

|

|







|







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
    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.
 *
 *------------------------------------------------------------------------
 */
void
TclZipfsFinalize(void)

{
    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 *) 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
 *
 *-------------------------------------------------------------------------
 */

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 */
{
    const char *archive;
    const char *result;

#ifdef _WIN32
    result = Tcl_FindExecutable(NULL);
#else
    result = Tcl_FindExecutable((*argvPtr)[0]);
#endif
    archive = Tcl_GetNameOfExecutable();
    TclZipfs_Init(NULL);

    /*
     * Look for init.tcl in one of the locations mounted later in this
     * function.
     */

    if (!TclZipfs_Mount(NULL, archive, ZIPFS_APP_MOUNT, NULL)) {
	int found;
	Tcl_Obj *vfsInitScript;

	TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
	Tcl_IncrRefCount(vfsInitScript);
	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
	    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;
	    }
	}
#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);
#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)) {
	    int found;
	    Tcl_Obj *vfsInitScript;

	    TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
	    Tcl_IncrRefCount(vfsInitScript);
	    if (Tcl_FSAccess(vfsInitScript, F_OK) == 0) {
		/*







|













|


















|
|







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
	    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 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], 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 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
	    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;
	    }
	}
#ifdef _WIN32
	Tcl_DStringFree(&ds);
#endif /* _WIN32 */
#endif /* SUPPORT_BUILTIN_ZIP_INSTALL */
    }
    return TCL_OK;
}

#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:
 */







|







|


|














<
|
>
|



|
<
<






|
<
|
>
|


|
<
<






|


>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|

>









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
	    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 result;
	    }
	}
#ifdef _WIN32
	Tcl_DStringFree(&ds);
#endif /* _WIN32 */
#endif /* SUPPORT_BUILTIN_ZIP_INSTALL */
    }
    return result;
}

#else /* !HAVE_ZLIB */

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_Mount, TclZipfs_MountBuffer, TclZipfs_Unmount --
 *
 *	Dummy version when no ZLIB support available.
 *
 *-------------------------------------------------------------------------
 */

int
TclZipfs_Mount(
    Tcl_Interp *interp,		/* Current interpreter. */

    TCL_UNUSED(const char *),	/* Path to ZIP file to mount. */
    TCL_UNUSED(const char *),	/* Mount point path. */
    TCL_UNUSED(const char *))		/* Password for opening the ZIP, or NULL if
				 * the ZIP is unprotected. */
{
    ZIPFS_ERROR(interp, "no zlib available");
    ZIPFS_ERROR_CODE(interp, "NO_ZLIB");


    return TCL_ERROR;
}

int
TclZipfs_MountBuffer(
    Tcl_Interp *interp,		/* Current interpreter. NULLable. */
    TCL_UNUSED(const void *),

    TCL_UNUSED(size_t),
    TCL_UNUSED(const char *),	/* Mount point path. */
    TCL_UNUSED(int))
{
    ZIPFS_ERROR(interp, "no zlib available");
    ZIPFS_ERROR_CODE(interp, "NO_ZLIB");


    return TCL_ERROR;
}

int
TclZipfs_Unmount(
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(const char *))	/* Mount point path. */
{
    ZIPFS_ERROR(interp, "no zlib available");
    ZIPFS_ERROR_CODE(interp, "NO_ZLIB");
    return TCL_ERROR;
}

const char *
TclZipfs_AppHook(
    TCL_UNUSED(int *), /*argcPtr*/
#ifdef _WIN32
    TCL_UNUSED(WCHAR ***)) /* argvPtr */
#else /* !_WIN32 */
    TCL_UNUSED(char ***))		/* Pointer to argv */
#endif /* _WIN32 */
{
    return NULL;
}

Tcl_Obj *
TclZipfs_TclLibrary(void)
{
    return NULL;
}

int
TclIsZipfsPath(
    TCL_UNUSED(const char *)) /* path */
{
    return 0;
}

#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
/*
 * tclZlib.c --
 *
 *	This file provides the interface to the Zlib library.
 *
 * Copyright (C) 2004-2005 Pascal Scheffers <[email protected]>
 * Copyright (C) 2005 Unitas Software B.V.
 * Copyright (c) 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.
 */





|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
 * tclZlib.c --
 *
 *	This file provides the interface to the Zlib library.
 *
 * Copyright © 2004-2005 Pascal Scheffers <[email protected]>
 * 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.
 */
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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;
    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







|







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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. */
    Tcl_Size outPos;
    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
285
286
287
288
289
290
291
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
	break;
    case Z_VERSION_ERROR:
	codeStr = "VERSION";
	break;
    case Z_NEED_DICT:
	codeStr = "NEED_DICT";
	codeStr2 = codeStrBuf;
	sprintf(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);
	break;
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(zError(code), -1));

    /*
     * Tricky point! We might pass NULL twice here (and will when the error
     * type is known).
     */

    Tcl_SetErrorCode(interp, "TCL", "ZLIB", codeStr, codeStr2, NULL);
}

static Tcl_Obj *
ConvertErrorToList(
    int code,			/* The zlib error code. */
    uLong adler)		/* The checksum expected (for Z_NEED_DICT) */
{







|




















|









|







285
286
287
288
289
290
291
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
	break;
    case Z_VERSION_ERROR:
	codeStr = "VERSION";
	break;
    case Z_NEED_DICT:
	codeStr = "NEED_DICT";
	codeStr2 = codeStrBuf;
	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;
	snprintf(codeStrBuf, sizeof(codeStrBuf), "%d", code);
	break;
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(zError(code), -1));

    /*
     * Tricky point! We might pass NULL twice here (and will when the error
     * type is known).
     */

    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) */
{
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
				 * 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_WideInt wideValue = 0;
    const char *valueStr;
    Tcl_Encoding latin1enc;
    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) {
	goto error;
    } else if (value != NULL) {

	valueStr = TclGetStringFromObj(value, &length);
	Tcl_UtfToExternal(NULL, latin1enc, valueStr, length, 0, NULL,

		headerPtr->nativeCommentBuf, MAX_COMMENT_LEN-1, NULL, &len,
		NULL);












	headerPtr->nativeCommentBuf[len] = '\0';
	headerPtr->header.comment = (Bytef *) headerPtr->nativeCommentBuf;
	if (extraSizePtr != NULL) {
	    *extraSizePtr += len;
	}
    }

    if (GetValue(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) {
	goto error;
    } else if (value != NULL) {

	valueStr = TclGetStringFromObj(value, &length);
	Tcl_UtfToExternal(NULL, latin1enc, valueStr, length, 0, NULL,

		headerPtr->nativeFilenameBuf, MAXPATHLEN-1, NULL, &len, NULL);














	headerPtr->nativeFilenameBuf[len] = '\0';
	headerPtr->header.name = (Bytef *) headerPtr->nativeFilenameBuf;
	if (extraSizePtr != NULL) {
	    *extraSizePtr += len;
	}
    }








|



















>

|
>


>
>
>
>
>
>
>
>
>
>
>
>

















>

|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
				 * 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;
    Tcl_Size length;
    Tcl_WideInt wideValue = 0;
    const char *valueStr;
    Tcl_Encoding latin1enc;
    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) {
	goto error;
    } else if (value != NULL) {
	Tcl_EncodingState state;
	valueStr = TclGetStringFromObj(value, &length);
	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) {
	goto error;
    } else if (value != NULL &&
	    Tcl_GetBooleanFromObj(interp, value, &headerPtr->header.hcrc)) {
	goto error;
    }

    if (GetValue(interp, dictObj, "filename", &value) != TCL_OK) {
	goto error;
    } else if (value != NULL) {
	Tcl_EncodingState state;
	valueStr = TclGetStringFromObj(value, &length);
	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;
	}
    }

484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
    /*
     * Ignore the 'size' field, since that is controlled by the size of the
     * input data.
     */

    if (GetValue(interp, dictObj, "time", &value) != TCL_OK) {
	goto error;
    } else if (value != NULL && Tcl_GetWideIntFromObj(interp, value,
	    &wideValue) != TCL_OK) {
	goto error;
    }
    headerPtr->header.time = wideValue;

    if (GetValue(interp, dictObj, "type", &value) != TCL_OK) {
	goto error;







|







514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
    /*
     * Ignore the 'size' field, since that is controlled by the size of the
     * input data.
     */

    if (GetValue(interp, dictObj, "time", &value) != TCL_OK) {
	goto error;
    } else if (value != NULL && TclGetWideIntFromObj(interp, value,
	    &wideValue) != TCL_OK) {
	goto error;
    }
    headerPtr->header.time = wideValue;

    if (GetValue(interp, dictObj, "type", &value) != TCL_OK) {
	goto error;
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

	    latin1enc = Tcl_GetEncoding(NULL, "iso8859-1");
	    if (latin1enc == NULL) {
		Tcl_Panic("no latin-1 encoding");
	    }
	}

	Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->comment, -1,
		&tmp);
	SetValue(dictObj, "comment", TclDStringToObj(&tmp));
    }
    SetValue(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");
	    if (latin1enc == NULL) {
		Tcl_Panic("no latin-1 encoding");
	    }
	}

	Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->name, -1,
		&tmp);
	SetValue(dictObj, "filename", TclDStringToObj(&tmp));
    }
    if (headerPtr->os != 255) {
	SetValue(dictObj, "os", Tcl_NewWideIntObj(headerPtr->os));
    }
    if (headerPtr->time != 0 /* magic - no time */) {
	SetValue(dictObj, "time", Tcl_NewWideIntObj(headerPtr->time));
    }







|

|














|

|







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

	    latin1enc = Tcl_GetEncoding(NULL, "iso8859-1");
	    if (latin1enc == NULL) {
		Tcl_Panic("no latin-1 encoding");
	    }
	}

	(void)Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->comment, TCL_INDEX_NONE,
		&tmp);
	SetValue(dictObj, "comment", Tcl_DStringToObj(&tmp));
    }
    SetValue(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");
	    if (latin1enc == NULL) {
		Tcl_Panic("no latin-1 encoding");
	    }
	}

	(void)Tcl_ExternalToUtfDString(latin1enc, (char *) headerPtr->name, TCL_INDEX_NONE,
		&tmp);
	SetValue(dictObj, "filename", Tcl_DStringToObj(&tmp));
    }
    if (headerPtr->os != 255) {
	SetValue(dictObj, "os", Tcl_NewWideIntObj(headerPtr->os));
    }
    if (headerPtr->time != 0 /* magic - no time */) {
	SetValue(dictObj, "time", Tcl_NewWideIntObj(headerPtr->time));
    }
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

static int
SetInflateDictionary(
    z_streamp strm,
    Tcl_Obj *compDictObj)
{
    if (compDictObj != NULL) {
	size_t length = 0;
	unsigned char *bytes = TclGetByteArrayFromObj(compDictObj, &length);




	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);




	return deflateSetDictionary(strm, bytes, length);
    }
    return Z_OK;
}

static inline int
Deflate(







|
|

>
>
>











|
|

>
>
>







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

static int
SetInflateDictionary(
    z_streamp strm,
    Tcl_Obj *compDictObj)
{
    if (compDictObj != NULL) {
	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) {
	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(
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
    }

    /*
     * 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) {
	    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);
	    Tcl_DStringFree(&cmdname);
	    goto error;
	}
	Tcl_ResetResult(interp);

	/*
	 * Create the command.







|









|







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
    }

    /*
     * I could do all this in C, but this is easier.
     */

    if (interp != NULL) {
	if (Tcl_EvalEx(interp, "::incr ::tcl::zlib::cmdcounter", TCL_INDEX_NONE, 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", (char *)NULL);
	    Tcl_DStringFree(&cmdname);
	    goto error;
	}
	Tcl_ResetResult(interp);

	/*
	 * Create the command.
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
void
Tcl_ZlibStreamSetCompressionDictionary(
    Tcl_ZlibStream zshandle,
    Tcl_Obj *compressionDictionaryObj)
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;

    if (compressionDictionaryObj && (NULL == TclGetBytesFromObj(NULL,
	    compressionDictionaryObj, NULL))) {
	/* Missing or invalid compression dictionary */
	compressionDictionaryObj = NULL;
    }
    if (compressionDictionaryObj != NULL) {
	if (Tcl_IsShared(compressionDictionaryObj)) {
	    compressionDictionaryObj =
		    Tcl_DuplicateObj(compressionDictionaryObj);







|
|







1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
void
Tcl_ZlibStreamSetCompressionDictionary(
    Tcl_ZlibStream zshandle,
    Tcl_Obj *compressionDictionaryObj)
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;

    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
    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;

    size_t size = 0, 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);
	}
	return TCL_ERROR;
    }

    bytes = TclGetBytesFromObj(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;







>
|






|




|







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
    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 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", (char *)NULL);
	}
	return TCL_ERROR;
    }

    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;
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
 *----------------------------------------------------------------------
 */

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
				 * may get less! */
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
    int e, i, listLen;
    size_t itemLen = 0, dataPos = 0;
    Tcl_Obj *itemObj;
    unsigned char *dataPtr, *itemPtr;
    size_t existing = 0;

    /*
     * Getting beyond the of stream, just return empty string.
     */

    if (zshPtr->streamEnd) {
	return TCL_OK;
    }

    if (NULL == TclGetBytesFromObj(zshPtr->interp, data, &existing)) {
	return TCL_ERROR;
    }

    if (zshPtr->mode == TCL_ZLIB_STREAM_INFLATE) {
	if (count == TCL_INDEX_NONE) {
	    /*
	     * 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;
	}







|



|
|


|









|




|







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
 *----------------------------------------------------------------------
 */

int
Tcl_ZlibStreamGet(
    Tcl_ZlibStream zshandle,	/* As obtained from Tcl_ZlibStreamInit */
    Tcl_Obj *data,		/* A place to append the data. */
    Tcl_Size count)			/* Number of bytes to grab as a maximum, you
				 * may get less! */
{
    ZlibStreamHandle *zshPtr = (ZlibStreamHandle *) zshandle;
    int e;
    Tcl_Size listLen, i, itemLen = 0, dataPos = 0;
    Tcl_Obj *itemObj;
    unsigned char *dataPtr, *itemPtr;
    Tcl_Size existing = 0;

    /*
     * Getting beyond the of stream, just return empty string.
     */

    if (zshPtr->streamEnd) {
	return TCL_OK;
    }

    if (NULL == Tcl_GetBytesFromObj(zshPtr->interp, data, &existing)) {
	return TCL_ERROR;
    }

    if (zshPtr->mode == TCL_ZLIB_STREAM_INFLATE) {
	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;
	}
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
	     * zlib will probably need more data to decompress.
	     */

	    if (zshPtr->currentInput) {
		Tcl_DecrRefCount(zshPtr->currentInput);
		zshPtr->currentInput = NULL;
	    }
	    Tcl_ListObjLength(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);
		Tcl_IncrRefCount(itemObj);
		zshPtr->currentInput = itemObj;
		zshPtr->stream.next_in = itemPtr;
		zshPtr->stream.avail_in = itemLen;

		/*
		 * And remove it from the list







|












|







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
	     * zlib will probably need more data to decompress.
	     */

	    if (zshPtr->currentInput) {
		Tcl_DecrRefCount(zshPtr->currentInput);
		zshPtr->currentInput = NULL;
	    }
	    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 = 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
	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);

	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));
		    Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "STATE",
			    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);
	    Tcl_IncrRefCount(itemObj);
	    zshPtr->currentInput = itemObj;
	    zshPtr->stream.next_in = itemPtr;
	    zshPtr->stream.avail_in = itemLen;

	    /*
	     * Remove it from the list.







|














|




















|







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
	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);
	    }
	};
	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));
		    Tcl_SetErrorCode(zshPtr->interp, "TCL", "ZIP", "STATE",
			    (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 = 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.
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
	    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) {
	    count = 0;
	    for (i=0; i<listLen; i++) {
		Tcl_ListObjIndex(NULL, zshPtr->outData, i, &itemObj);
		(void) TclGetByteArrayFromObj(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)
		&& (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;

		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;

		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);







|
|



|
















|







|
|
|








|







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
	    if (zshPtr->currentInput) {
		Tcl_DecrRefCount(zshPtr->currentInput);
		zshPtr->currentInput = 0;
	    }
	    inflateEnd(&zshPtr->stream);
	}
    } else {
	TclListObjLength(NULL, zshPtr->outData, &listLen);
	if (count < 0) {
	    count = 0;
	    for (i=0; i<listLen; i++) {
		Tcl_ListObjIndex(NULL, zshPtr->outData, i, &itemObj);
		(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) &&
		(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 = 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 {
		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
    Tcl_Interp *interp,
    int format,
    Tcl_Obj *data,
    int level,
    Tcl_Obj *gzipHeaderDictObj)
{
    int wbits = 0, e = 0, extraSize = 0;
    size_t 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);
    if (inData == NULL) {
	return TCL_ERROR;
    }

    /*
     * Compressed format is specified by the wbits parameter. See zlib.h for
     * details.







|















|







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
    Tcl_Interp *interp,
    int format,
    Tcl_Obj *data,
    int level,
    Tcl_Obj *gzipHeaderDictObj)
{
    int wbits = 0, e = 0, extraSize = 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 = 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
    }

    if (e != Z_OK) {
	goto error;
    }

    /*
     * 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;








|







1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
    }

    if (e != Z_OK) {
	goto error;
    }

    /*
     * 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
 */

int
Tcl_ZlibInflate(
    Tcl_Interp *interp,
    int format,
    Tcl_Obj *data,
    size_t bufferSize,
    Tcl_Obj *gzipHeaderDictObj)
{
    int wbits = 0, e = 0;
    size_t 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);
    if (inData == NULL) {
	return TCL_ERROR;
    }

    /*
     * Compressed format is specified by the wbits parameter. See zlib.h for
     * details.







|



|










|







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
 */

int
Tcl_ZlibInflate(
    Tcl_Interp *interp,
    int format,
    Tcl_Obj *data,
    Tcl_Size bufferSize,
    Tcl_Obj *gzipHeaderDictObj)
{
    int wbits = 0, e = 0;
    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 = Tcl_GetBytesFromObj(interp, data, &inLen);
    if (inData == NULL) {
	return TCL_ERROR;
    }

    /*
     * Compressed format is specified by the wbits parameter. See zlib.h for
     * details.
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
 *----------------------------------------------------------------------
 */

unsigned int
Tcl_ZlibCRC32(
    unsigned int crc,
    const unsigned char *buf,
    size_t 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)
{
    return adler32(adler, (Bytef *) buf, len);
}

/*
 *----------------------------------------------------------------------
 *







|









|







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
 *----------------------------------------------------------------------
 */

unsigned int
Tcl_ZlibCRC32(
    unsigned int crc,
    const unsigned char *buf,
    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,
    Tcl_Size len)
{
    return adler32(adler, (Bytef *) buf, len);
}

/*
 *----------------------------------------------------------------------
 *
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
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;


    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
    };

    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 */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?");
	    return TCL_ERROR;
	}
	data = TclGetBytesFromObj(interp, objv[2], &dlen);
	if (data == NULL) {
	    return TCL_ERROR;
	}
	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)));
	return TCL_OK;
    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);
	if (data == NULL) {
	    return TCL_ERROR;
	}
	if (objc>3 && Tcl_GetIntFromObj(interp, objv[3],
		(int *) &start) != TCL_OK) {
	    return TCL_ERROR;
	}







|
|
>
>












|










|






|



















|







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
static int
ZlibCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    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 (command) {
    case CMD_ADLER:			/* adler32 str ?startvalue?
					 * -> checksum */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?");
	    return TCL_ERROR;
	}
	data = Tcl_GetBytesFromObj(interp, objv[2], &dlen);
	if (data == NULL) {
	    return TCL_ERROR;
	}
	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)));
	return TCL_OK;
    case CMD_CRC:			/* crc32 str ?startvalue?
					 * -> checksum */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?startValue?");
	    return TCL_ERROR;
	}
	data = Tcl_GetBytesFromObj(interp, objv[2], &dlen);
	if (data == NULL) {
	    return TCL_ERROR;
	}
	if (objc>3 && Tcl_GetIntFromObj(interp, objv[3],
		(int *) &start) != TCL_OK) {
	    return TCL_ERROR;
	}
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
    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],
		    &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 \
					 *    ?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],
		    &wideLen) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (wideLen < MIN_NONSTREAM_BUFFER_SIZE
		    || wideLen > MAX_BUFFER_SIZE) {
		goto badBuffer;
	    }







|



















|







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
    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 (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 \
					 *    ?bufferSize?
					 *	-> decompressedData */
	if (objc < 3 || objc > 4) {
	    Tcl_WrongNumArgs(interp, 2, objv, "data ?bufferSize?");
	    return TCL_ERROR;
	}
	if (objc > 3) {
	    if (TclGetWideIntFromObj(interp, objv[3],
		    &wideLen) != TCL_OK) {
		return TCL_ERROR;
	    }
	    if (wideLen < MIN_NONSTREAM_BUFFER_SIZE
		    || wideLen > MAX_BUFFER_SIZE) {
		goto badBuffer;
	    }
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169

	    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],
			&wideLen) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (wideLen < MIN_NONSTREAM_BUFFER_SIZE
			|| wideLen > MAX_BUFFER_SIZE) {
		    goto badBuffer;
		}







|







2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208

	    if (Tcl_GetIndexFromObj(interp, objv[i], gunzipopts, "option", 0,
		    &option) != TCL_OK) {
		return TCL_ERROR;
	    }
	    switch (option) {
	    case 0:
		if (TclGetWideIntFromObj(interp, objv[i+1],
			&wideLen) != TCL_OK) {
		    return TCL_ERROR;
		}
		if (wideLen < MIN_NONSTREAM_BUFFER_SIZE
			|| wideLen > MAX_BUFFER_SIZE) {
		    goto badBuffer;
		}
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
	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);
    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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibStreamSubcmd --







|








|







2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
	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", (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", (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * ZlibStreamSubcmd --
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
    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
    };
    int i, format, mode = 0, option, level;
    enum objIndices {
	OPT_COMPRESSION_DICTIONARY = 0,
	OPT_GZIP_HEADER = 1,
	OPT_COMPRESSION_LEVEL = 2,
	OPT_END = -1
    };







|







2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
    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
    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) {
	return TCL_ERROR;
    }

    /*
     * The format determines the compression mode and the options that may be
     * specified.
     */

    switch ((enum zlibFormats) format) {
    case FMT_DEFLATE:
	desc = compressionOpts;
	mode = TCL_ZLIB_STREAM_DEFLATE;
	format = TCL_ZLIB_FORMAT_RAW;
	break;
    case FMT_INFLATE:
	desc = expansionOpts;







|








|







2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
    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,
	    &fmt) != TCL_OK) {
	return TCL_ERROR;
    }

    /*
     * The format determines the compression mode and the options that may be
     * specified.
     */

    switch (fmt) {
    case FMT_DEFLATE:
	desc = compressionOpts;
	mode = TCL_ZLIB_STREAM_DEFLATE;
	format = TCL_ZLIB_FORMAT_RAW;
	break;
    case FMT_INFLATE:
	desc = expansionOpts;
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361

    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_AddErrorInfo(interp, "\n    (in -level option)");
	return TCL_ERROR;
    }

    if (compDictObj) {
	if (NULL == TclGetBytesFromObj(interp, compDictObj, NULL)) {
	    return TCL_ERROR;
	}
    }

    /*
     * Construct the stream now we know its configuration.
     */







|





|







2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400

    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", (char *)NULL);
	Tcl_AddErrorInfo(interp, "\n    (in -level option)");
	return TCL_ERROR;
    }

    if (compDictObj) {
	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
    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
    };
    Tcl_Channel chan;
    int chanMode, format, mode = 0, level, i, option;
    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};
    Tcl_Obj *headerObj = NULL, *compDictObj = NULL;
    int limit = DEFAULT_BUFFER_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) {
	return TCL_ERROR;
    }
    switch ((enum zlibFormats) format) {
    case FMT_DEFLATE:
	mode = TCL_ZLIB_STREAM_DEFLATE;
	format = TCL_ZLIB_FORMAT_RAW;
	pushOptions = pushCompressOptions;
	break;
    case FMT_INFLATE:
	mode = TCL_ZLIB_STREAM_INFLATE;







|

|







|

|
>







|


|







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
    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;
    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} option;
    Tcl_Obj *headerObj = NULL, *compDictObj = NULL;
    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,
	    &fmt) != TCL_OK) {
	return TCL_ERROR;
    }
    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;
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
    /*
     * 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);
	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);
	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) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "value missing for %s option", pushOptions[option]));
	    Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", NULL);
	    return TCL_ERROR;
	}
	switch ((enum pushOptionsEnum) option) {
	case poHeader:
	    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) {
		goto genericOptionError;
	    }
	    if (level < 0 || level > 9) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"level must be 0 to 9", -1));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL",
			NULL);
		goto genericOptionError;
	    }
	    break;
	case poLimit:
	    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);
		goto genericOptionError;
	    }
	    break;
	case poDictionary:
	    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);
		goto genericOptionError;
	    }
	    compDictObj = objv[i];
	    break;
	}
    }

    if (compDictObj && (NULL == TclGetBytesFromObj(interp, compDictObj, NULL))) {
	return TCL_ERROR;
    }

    if (ZlibStackChannelTransform(interp, mode, format, level, limit, chan,
	    headerObj, compDictObj) == NULL) {
	return TCL_ERROR;
    }







|




|
|
















|


|














|











|








|







|







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
    /*
     * 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", (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",TCL_INDEX_NONE));
	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) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "value missing for %s option", pushOptions[option]));
	    Tcl_SetErrorCode(interp, "TCL", "ZIP", "NOVAL", (char *)NULL);
	    return TCL_ERROR;
	}
	switch (option) {
	case poHeader:
	    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) {
		goto genericOptionError;
	    }
	    if (level < 0 || level > 9) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"level must be 0 to 9", -1));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMPRESSIONLEVEL",
			(char *)NULL);
		goto genericOptionError;
	    }
	    break;
	case poLimit:
	    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", (char *)NULL);
		goto genericOptionError;
	    }
	    break;
	case poDictionary:
	    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", (char *)NULL);
		goto genericOptionError;
	    }
	    compDictObj = objv[i];
	    break;
	}
    }

    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;
    }
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
ZlibStreamCmd(
    void *cd,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd;
    int command, 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
    };

    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) {
    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);








|









|











|







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
ZlibStreamCmd(
    void *cd,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd;
    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 (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
	}
	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)));
	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)







|







2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
	}
	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_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)
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
ZlibStreamAddCmd(
    void *cd,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd;
    int index, 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
    };

    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 */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_SYNC_FLUSH;
	    }
	    break;







|






|







|







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
ZlibStreamAddCmd(
    void *cd,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd;
    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 (index) {
	case ao_flush: /* -flush */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_SYNC_FLUSH;
	    }
	    break;
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
	    }
	    break;
	case ao_buffer: /* -buffer */
	    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);
		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);
		return TCL_ERROR;
	    }
	    break;
	case ao_dictionary:
	    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);
		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);
	    return TCL_ERROR;
	}
    }
    if (flush == -1) {
	flush = 0;
    }

    /*
     * Set the compression dictionary if requested.
     */

    if (compDictObj != NULL) {
	size_t len = 0;

	if (NULL == TclGetBytesFromObj(interp, compDictObj, &len)) {
	    return TCL_ERROR;
	}

	if (len == 0) {
	    compDictObj = NULL;
	}
	Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj);







|









|








|










|












|

|







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
	    }
	    break;
	case ao_buffer: /* -buffer */
	    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", (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", (char *)NULL);
		return TCL_ERROR;
	    }
	    break;
	case ao_dictionary:
	    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", (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", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    if (flush == -1) {
	flush = 0;
    }

    /*
     * Set the compression dictionary if requested.
     */

    if (compDictObj != NULL) {
	Tcl_Size len = 0;

	if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, &len)) {
	    return TCL_ERROR;
	}

	if (len == 0) {
	    compDictObj = NULL;
	}
	Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj);
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
ZlibStreamPutCmd(
    void *cd,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd;
    int index, 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
    };

    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 */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_SYNC_FLUSH;
	    }
	    break;







|






|







|







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
ZlibStreamPutCmd(
    void *cd,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_ZlibStream zstream = (Tcl_ZlibStream)cd;
    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 (index) {
	case po_flush: /* -flush */
	    if (flush >= 0) {
		flush = -2;
	    } else {
		flush = Z_SYNC_FLUSH;
	    }
	    break;
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
	    }
	    break;
	case po_dictionary:
	    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);
		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);
	    return TCL_ERROR;
	}
    }
    if (flush == -1) {
	flush = 0;
    }

    /*
     * Set the compression dictionary if requested.
     */

    if (compDictObj != NULL) {
	size_t len = 0;

	if (NULL == TclGetBytesFromObj(interp, compDictObj, &len)) {
	    return TCL_ERROR;
	}
	if (len == 0) {
	    compDictObj = NULL;
	}
	Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj);
    }







|









|












|

|







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
	    }
	    break;
	case po_dictionary:
	    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", (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", (char *)NULL);
	    return TCL_ERROR;
	}
    }
    if (flush == -1) {
	flush = 0;
    }

    /*
     * Set the compression dictionary if requested.
     */

    if (compDictObj != NULL) {
	Tcl_Size len = 0;

	if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, &len)) {
	    return TCL_ERROR;
	}
	if (len == 0) {
	    compDictObj = NULL;
	}
	Tcl_ZlibStreamSetCompressionDictionary(zstream, compDictObj);
    }
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
    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);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    ExtractHeader(&zshPtr->gzHeaderPtr->header, resultObj);
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;







|







2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
    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", (char *)NULL);
	return TCL_ERROR;
    }

    TclNewObj(resultObj);
    ExtractHeader(&zshPtr->gzHeaderPtr->header, resultObj);
    Tcl_SetObjResult(interp, resultObj);
    return TCL_OK;
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
    if (optionName && (strcmp(optionName, "-dictionary") == 0)
	    && (cd->format != TCL_ZLIB_FORMAT_GZIP)) {
	Tcl_Obj *compDictObj;
	int code;

	TclNewStringObj(compDictObj, value, strlen(value));
	Tcl_IncrRefCount(compDictObj);
	if (NULL == TclGetBytesFromObj(interp, compDictObj, NULL)) {
	    Tcl_DecrRefCount(compDictObj);
	    return TCL_ERROR;
	}
	if (cd->compDictObj) {
	    TclDecrRefCount(cd->compDictObj);
	}
	cd->compDictObj = compDictObj;







|







3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
    if (optionName && (strcmp(optionName, "-dictionary") == 0)
	    && (cd->format != TCL_ZLIB_FORMAT_GZIP)) {
	Tcl_Obj *compDictObj;
	int code;

	TclNewStringObj(compDictObj, value, strlen(value));
	Tcl_IncrRefCount(compDictObj);
	if (NULL == Tcl_GetBytesFromObj(interp, compDictObj, (Tcl_Size *)NULL)) {
	    Tcl_DecrRefCount(compDictObj);
	    return TCL_ERROR;
	}
	if (cd->compDictObj) {
	    TclDecrRefCount(cd->compDictObj);
	}
	cd->compDictObj = compDictObj;
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
		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);
		return TCL_ERROR;
	    }

	    /*
	     * Try to actually do the flush now.
	     */

	    return ZlibTransformFlush(interp, cd, 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);
		return TCL_ERROR;
	    }
	}
    }

    if (setOptionProc == NULL) {
	if (cd->format == TCL_ZLIB_FORMAT_GZIP) {







|


















|







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
		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", (char *)NULL);
		return TCL_ERROR;
	    }

	    /*
	     * Try to actually do the flush now.
	     */

	    return ZlibTransformFlush(interp, cd, 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", (char *)NULL);
		return TCL_ERROR;
	    }
	}
    }

    if (setOptionProc == NULL) {
	if (cd->format == TCL_ZLIB_FORMAT_GZIP) {
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464

	if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) {
	    crc = cd->outStream.adler;
	} else {
	    crc = cd->inStream.adler;
	}

	sprintf(buf, "%lu", crc);
	if (optionName == NULL) {
	    Tcl_DStringAppendElement(dsPtr, "-checksum");
	    Tcl_DStringAppendElement(dsPtr, buf);
	} else {
	    Tcl_DStringAppend(dsPtr, buf, -1);
	    return TCL_OK;
	}







|







3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504

	if (cd->mode == TCL_ZLIB_STREAM_DEFLATE) {
	    crc = cd->outStream.adler;
	} else {
	    crc = cd->inStream.adler;
	}

	snprintf(buf, sizeof(buf), "%lu", crc);
	if (optionName == NULL) {
	    Tcl_DStringAppendElement(dsPtr, "-checksum");
	    Tcl_DStringAppendElement(dsPtr, buf);
	} else {
	    Tcl_DStringAppend(dsPtr, buf, -1);
	    return TCL_OK;
	}
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
		Tcl_DStringAppendElement(dsPtr,
			TclGetString(cd->compDictObj));
	    } else {
		Tcl_DStringAppendElement(dsPtr, "");
	    }
	} else {
	    if (cd->compDictObj) {
		size_t length;
		const char *str = TclGetStringFromObj(cd->compDictObj, &length);

		Tcl_DStringAppend(dsPtr, str, length);
	    }
	    return TCL_OK;
	}
    }







|







3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
		Tcl_DStringAppendElement(dsPtr,
			TclGetString(cd->compDictObj));
	    } else {
		Tcl_DStringAppendElement(dsPtr, "");
	    }
	} else {
	    if (cd->compDictObj) {
		Tcl_Size length;
		const char *str = TclGetStringFromObj(cd->compDictObj, &length);

		Tcl_DStringAppend(dsPtr, str, length);
	    }
	    return TCL_OK;
	}
    }
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
	    cd->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);
    }

    if (format == TCL_ZLIB_FORMAT_RAW) {
	wbits = WBITS_RAW;
    } else if (format == TCL_ZLIB_FORMAT_ZLIB) {
	wbits = WBITS_ZLIB;
    } else if (format == TCL_ZLIB_FORMAT_GZIP) {







|







3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
	    cd->inHeader.header.comm_max = MAX_COMMENT_LEN - 1;
	}
    }

    if (compDictObj != NULL) {
	cd->compDictObj = Tcl_DuplicateObj(compDictObj);
	Tcl_IncrRefCount(cd->compDictObj);
	Tcl_GetBytesFromObj(NULL, cd->compDictObj, (Tcl_Size *)NULL);
    }

    if (format == TCL_ZLIB_FORMAT_RAW) {
	wbits = WBITS_RAW;
    } else if (format == TCL_ZLIB_FORMAT_ZLIB) {
	wbits = WBITS_ZLIB;
    } else if (format == TCL_ZLIB_FORMAT_GZIP) {
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949

    /*
     * 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);

    /*
     * Create the public scripted interface to this file's functionality.
     */

    Tcl_CreateObjCommand(interp, "zlib", ZlibCmd, 0, 0);








|







3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989

    /*
     * 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}", TCL_INDEX_NONE, 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

    TclRegisterCommandTypeName(ZlibStreamCmd, "zlibStream");

    /*
     * Formally provide the package as a Tcl built-in.
     */

    return Tcl_PkgProvideEx(interp, "zlib", TCL_ZLIB_VERSION, NULL);
}

/*
 *----------------------------------------------------------------------
 *	Stubs used when a suitable zlib installation was not found during
 *	configure.
 *----------------------------------------------------------------------







|







4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019

    TclRegisterCommandTypeName(ZlibStreamCmd, "zlibStream");

    /*
     * Formally provide the package as a Tcl built-in.
     */

    return Tcl_PkgProvideEx(interp, "tcl::zlib", TCL_ZLIB_VERSION, NULL);
}

/*
 *----------------------------------------------------------------------
 *	Stubs used when a suitable zlib installation was not found during
 *	configure.
 *----------------------------------------------------------------------
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
    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)







|







4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
    int format,
    int level,
    Tcl_Obj *dictObj,
    Tcl_ZlibStream *zshandle)
{
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
	Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", (char *)NULL);
    }
    return TCL_ERROR;
}

int
Tcl_ZlibStreamClose(
    Tcl_ZlibStream zshandle)
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
    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,







|














|






|
|
|






|
|
|







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
    int format,
    Tcl_Obj *data,
    int level,
    Tcl_Obj *gzipHeaderDictObj)
{
    if (interp) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
	Tcl_SetErrorCode(interp, "TCL", "UNIMPLEMENTED", (char *)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", (char *)NULL);
    }
    return TCL_ERROR;
}

unsigned int
Tcl_ZlibCRC32(
    TCL_UNUSED(unsigned int),
    TCL_UNUSED(const unsigned char *),
    TCL_UNUSED(size_t))
{
    return 0;
}

unsigned int
Tcl_ZlibAdler32(
    TCL_UNUSED(unsigned int),
    TCL_UNUSED(const unsigned char *),
    TCL_UNUSED(size_t))
{
    return 0;
}

void
Tcl_ZlibStreamSetCompressionDictionary(
    Tcl_ZlibStream zshandle,

Changes to library/auto.tcl.

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.
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

# auto_reset --
#





|
|







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 © 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 --
#
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

100

101

102




103
104
105
106
107


108
109
110


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    } 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)
        }

	catch {
      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]
	    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]} {
  	        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}
            }
          }
        }
      }
   }

	# 2. In the package script directory registered within the
	#    configuration of the package itself.

	catch {
	    lappend dirs [::${basename}::pkgconfig get scriptdir,runtime]
	}







|
|
|


|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
>
|
>
|
>
>
>
>
|
<
|
|
|
>
>
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

111
112
113
114
115
116
117
118
119
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)
	}

	catch {
	    set found 0
	    set root [zipfs root]
	    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 {$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 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
	#
	# ../../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]
	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
    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]

	# 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
            }
	    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







|
|
|
|
|







|














|
|




|
|
|
|


|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
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]
	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]
	}
    }
    # 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]

	# 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
	    }
	    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

# 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"
    }

    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"







|







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"
    }

    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
    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
	    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"
		}
	    }
	    close $f
	} msg opts]
	if {$error} {
	    catch {close $f}
	    cd $oldDir







|




|







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 \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 -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
	    # 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

	    foreach cmd $initCommands {
		eval $cmd
	    }
	}
    }
    proc cleanup {} {







|







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 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
    variable scriptFile
    variable contextStack
    variable imports

    set scriptFile $file

    set fid [open $file]
    fconfigure $fid -encoding utf-8 -eofchar \032
    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]}
    }
    return $index
}

# auto_mkindex_parser::hook command
#
# Registers a Tcl command to evaluate when initializing the child interpreter







|



















|







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 \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]}
    }
    return $index
}

# auto_mkindex_parser::hook command
#
# Registers a Tcl command to evaluate when initializing the child interpreter
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

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
    } else {
        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]

	# 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
    } else {
        $parser alias $name $fakeName
    }
    return
}

# auto_mkindex_parser::fullname --
#
# Used by commands like "proc" within the auto_mkindex parser.  Returns the







|

|








|
|











|
|
|

|







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

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
    } else {
	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]

	# 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
    } else {
	$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
# 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
            }
        }
    }

    if {[namespace qualifiers $name] eq ""} {
        set name [namespace tail $name]
    } elseif {![string match ::* $name]} {
        set name "::$name"
    }

    # Earlier, mkindex replaced all $'s with \0.  Now, we have to reverse that
    # replacement.
    return [string map [list \0 \$] $name]
}








|
|
|
|
|
|



|

|







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
	    }
	}
    }

    if {[namespace qualifiers $name] eq ""} {
	set name [namespace tail $name]
    } elseif {![string match ::* $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
    # 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} \
	    $name $filenameParts \n]
    return
}

if {[llength $::auto_mkindex_parser::initCommands]} {
    return
}







|







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 -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
    } 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
	# procedure name.

	auto_mkindex_parser::commandInit tbcload::bcproc {name args} {
	    indexEntry $name
	}
    }
}







|







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 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
# 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

            set name [lindex $args 0]
            set args [lrange $args 1 end]

            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"}
        }
	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
		$parser eval [list ::proc $name {} {}]
	    }
	}
    }
}

# AUTO MKINDEX:  oo::class create name ?definition?







|
|
|

|
|

|

|
|
|
|
|
|
|
|
|
|
|
|












|







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

	    set name [lindex $args 0]
	    set args [lrange $args 1 end]

	    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"}
	}
	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 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
#----------------------------------------------------------------------
#
# 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

# 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
# access to the Registry on Windows systems.

uplevel \#0 {
    package require msgcat 1.6
    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]]]

#----------------------------------------------------------------------
#
# clock --
#
#	Manipulate times.
#











|
>





|
<

<
|
<
<
<
<
<
<





|







1
2
3
4
5
6
7
8
9
10
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 © 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.
#
#----------------------------------------------------------------------

# msgcat 1.7 features are used.



package require msgcat 1.7







# 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 [info library]]

#----------------------------------------------------------------------
#
# clock --
#
#	Manipulate times.
#
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    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 --







<

<







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::mclocale

    namespace import ::msgcat::mcpackagelocale

}

#----------------------------------------------------------------------
#
# ::tcl::clock::Initialize --
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

    ::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
    # earlier date?)

    ::msgcat::mcset ro GREGORIAN_CHANGE_DATE 2422063

    # Greece

    ::msgcat::mcset el GREGORIAN_CHANGE_DATE 2423480







|







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 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
    variable MINWIDE -9223372036854775808
    variable MAXWIDE 9223372036854775807

    # Day before Leap Day

    variable FEB_28	       58








    # 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:







>
>
>
>
>
>
>







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
    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:
306
307
308
309
310
311
312
313
314
315
316
317
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
    # 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
	{-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
	{-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}
							 :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
	{-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
	{-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 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 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}
							 :Asia/Beirut
        {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 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







|
|
|
|
|



|



|

|
|




|
|







|
|


|


|
|

|




|







304
305
306
307
308
309
310
311
312
313
314
315
316
317
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
    # 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
	{-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
	{-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}
							 :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
	{-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
	{-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 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 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}
							 :Asia/Beirut
	{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 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
	{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 \







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
    }]



















































































































































    # 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
	cdt	-0500 \
	mst	-0700 \
	mdt	-0600 \
	pst	-0800 \
	pdt	-0700 \
	yst	-0900 \
	ydt	-0800 \


	hst	-1000 \
	hdt	-0900 \
	cat	-1000 \
	ahst	-1000 \
	nt	-1100 \
	idlw	-1200 \
	cet	+0100 \







>
>







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
	wast	+0700 \
	wadt	+0800 \
	jt	+0730 \
	cct	+0800 \
	jst	+0900 \
	kst     +0900 \
	cast	+0930 \
        jdt     +1000 \
        kdt     +1000 \
	cadt	+1030 \
	east	+1000 \
	eadt	+1030 \
	gst	+1000 \
	nzt	+1200 \
	nzst	+1200 \
	nzdt	+1300 \







|
|







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 \
	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
	x	-1100 \
	y	-1200 \
	z	+0000 \
    ]

    # Caches

    variable LocaleNumeralCache {};	# Dictionary whose keys are locale
					# names and whose values are pairs
					# 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
					# the time zone is unknown and 0
    					# 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
}
::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
			}
		    }
		    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 \
			    { [expr { [dict get $date localSeconds] \
					  / 3600 % 24}]}
		    }
		    I {			# Hour AM/PM, with leading zero
			append formatString %02d

			append substituents \
			    { [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]
				       % 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!
			append formatString %s
			append substituents { [FormatStarDate $date]}
		    }
		    s {			# Seconds from the Posix Epoch
			append formatString %s


			append substituents { [dict get $date seconds]}
		    }
		    S {			# Second of the minute, with

			# leading zero
			append formatString %02d
			append substituents \
			    { [expr { [dict get $date localSeconds]
				      % 60 }]}
		    }
		    t {			# A literal tab character
			append formatString \t
		    }
		    u {			# Day of the week (1-Monday, 7-Sunday)
			append formatString %1d
			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]]}]
		    }
		    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
		    }
		}
	    }
	}
    }

    # Clean up any improperly terminated groups

    switch -exact -- $state {
	percent {
	    append formatString %%
	}
	percentE {
	    append retval %%E
	}
	percentO {
	    append retval %%O
	}
    }

    proc $procName {clockval timezone} "
        $preFormatCode
        return \[::format [list $formatString] $substituents\]
    "

    #    puts [list $procName [info args $procName] [info body $procName]]

    return $procName
}

#----------------------------------------------------------------------
#
# 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 {}

    # Check the count of args

    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
    set timezone [GetSystemTimeZone]

    # Pick up command line options.

    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"
	    }
	}
    }

    # 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($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
    }
}

#----------------------------------------------------------------------
#
# 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 the data for time changes in the given zone

    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!
			append re {Stardate\s+([-+]?\d+)(\d\d\d)[.](\d)}



			incr captureCount
			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.
			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 \[" \
			    "::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]
			append postcode {::scan $field} [incr captureCount] \
			    { %d dow} \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
			    }
		    }
		    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

			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 \[" \
			    "::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 } \[ \
			    {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 {}
			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 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"
		    }
		    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 {}
	    }
	    %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]
			append postcode "dict set date hour \[" \
			    "dict get " [list $lookup] " \$field" \

			    [incr captureCount] \
			    "\]\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.
#
#----------------------------------------------------------------------

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]
}



#----------------------------------------------------------------------
#
# 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.
#
# Results:
#	Returns a two-element list.  The first is a regexp that matches any
#	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 } {
    # 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.

    set prefixMapping [dict create]
    set successors [dict create {} {}]

    # Walk the key-value pairs

    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 \
		[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.
#
#----------------------------------------------------------------------

proc ::tcl::clock::MakeUniquePrefixRegexp { successors
					  uniquePrefixMapping
					  prefixString } {

    # Get the characters that may follow the current prefix string

    set schars [lsort -ascii [dict keys [dict get $successors $prefixString]]]
    if { [llength $schars] == 0 } {
	return {}
    }

    # 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 |
    }

    # 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 ")"
    }

    return $re
}

#----------------------------------------------------------------------
#
# 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
	}

	# Accumulate the field positions that are used in the current field
	# grouping.

	set fieldPos [list]
	set ok true
	foreach field $fieldSet {
	    if { ! [dict exists $dateFields $field] } {
		set ok 0
		break
	    }
	    lappend fieldPos [dict get $dateFields $field]
	}

	# 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
}

#----------------------------------------------------------------------
#
# 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} } {
	if { $::tcl_platform(platform) ne {windows} } {
	    # On a non-windows platform, the 'system' locale is the same as
	    # the 'current' locale

	    set locale current
	} 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



	    }
	}


    }
    if { $locale eq {current}} {
	set locale [mclocale]
    }

    # Eventually load the locale
    mcpackagelocale set $locale
}

#----------------------------------------------------------------------
#
# LoadWindowsDateTimeFormats --
#
#	Load the date/time formats from the Control Panel in Windows and







|
|
<
<
<
<
<
<
<
<
|








|
|
|




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
|
>
>
|
<
<
<
<
<
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
>
>
|
<
|
>
|
<
|
|
<
|
<
<
|
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
|
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
>
>
>
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
>
|
>
>
>
|
|
|
<
<
|
<
<
<
<
>
|
>
>
>
|
>
>
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
>
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
<
<
<
<
<
<
<
<

<
<
|


|
<
<
<






|
<
<
<
<
|
<
<
|
<
|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<

<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|




















|
<
|
|
<
|
<
<
<
<
<
|
>
|
>
|
|
>
>
>
>
>
|
|
>
>
|
>
|
>
>
|
>
>
>
|

>
>
|
<
<

>
|
<







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 LocFmtMap [dict create];	# Dictionary with localized format maps









    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.
    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 mcLocales	 [dict create];	# Dictionary with loaded locales
    variable mcMergedCat [dict create];	# Dictionary with merged locale catalogs
}
::tcl::clock::Initialize

#----------------------------------------------------------------------

























































































































































































# mcget --













#
#	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.





#
# Arguments:



































































#	loc	The locale used for translation.












#

# Results:





#	Returns the dictionary object as whole catalog of the package/locale.
#
proc ::tcl::clock::mcget {loc} {

    variable mcMergedCat
    switch -- $loc system {
	set loc [GetSystemLocale]

    } current {
	set loc [mclocale]

    }


    if {$loc ne {}} {

    	set loc [string tolower $loc]

    }












































































    # try to retrieve now if already available:
    if {[dict exists $mcMergedCat $loc]} {
	return [dict get $mcMergedCat $loc]
    }






































































































    # get locales list for given locale (de_de -> {de_de de {}})

    variable mcLocales











    if {[dict exists $mcLocales $loc]} {




	set loclist [dict get $mcLocales $loc]

    } else {


	# save current locale:














	set prevloc [mclocale]

	# lazy load catalog on demand (set it will load the catalog)

















	mcpackagelocale set $loc

	set loclist [msgcat::mcutil::getpreferences $loc]

	dict set $mcLocales $loc $loclist


























	# restore:

	if {$prevloc ne $loc} {









































	   mcpackagelocale set $prevloc

















	}

    }

    # get whole catalog:

    mcMerge $loclist





}


















































































































































































































































































































































































# mcMerge --

#
#	Merge message catalog dictionaries to one dictionary.
#
# Arguments:










#	locales		List of locales to merge.





#
# 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]


    }




    # 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





	} else {













	    # be sure a duplicate is created, don't overwrite {} (common) locale:
























	    set mrgcat [dict merge $mrgcat [dict create L $loc]]





	}








    } else {
	if {[dict exists $Msgs $ns $loc]} {



















	    set mrgcat [dict get $Msgs $ns $loc]












	    dict set mrgcat L $loc










	} else {













	    # be sure a duplicate is created, don't overwrite {} (common) locale:
	    set mrgcat [dict create L $loc]
	}










    }



    dict set mcMergedCat $loc $mrgcat


    # return smart reference (shared dict as object with exact one ref-counter)
    return $mrgcat

}





























































































































































#----------------------------------------------------------------------
#















# GetSystemLocale --


#
















#	Determines the system locale, which corresponds to "system"
#	keyword for locale parameter of 'clock' command.
#








# Parameters:


#	None.
#
# Results:
#	Returns the system locale.



#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::GetSystemLocale {} {




    if { $::tcl_platform(platform) ne {windows} } {


	# On a non-windows platform, the 'system' locale is the same as

	# the 'current' locale


































	return [mclocale]


    }

























    # 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



    }































    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 } {
    switch -- $locale system {

    	set locale [GetSystemLocale]
    } current {

	set locale [mclocale]





    }
    # 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.1 }] } {
	    # 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]] \
			    tclreg*[expr {[::tcl::pkgconfig get debug] ? {g} : {}}].dll] 0 \
		] registry
	    }}
	}
	if { [namespace which -command ::registry] ne "" } {
	    set res 1
	}


    }
    proc ::tcl::clock::_hasRegistry {} [list return $res]
    return $res

}

#----------------------------------------------------------------------
#
# LoadWindowsDateTimeFormats --
#
#	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
# 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 { ![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   {}
	    } $unquoted]
	    if { $quoted eq {} } {
		set quote '
	    } else {
		set quote $quoted
	    }
	}







<
|



















|
|







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


    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   {}
	    } $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
		d    %e
		MMMM %B
		MMM  %b
		MM   %m
		M    %N
		yyyy %Y
		yy   %y
                y    %y
                gg   {}
	    } $unquoted]
	    if { $quoted eq {} } {
		set quote '
	    } else {
		set quote $quoted
	    }
	}







|
|







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   {}
	    } $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
#
#	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]


#
# Results:
#	Returns the string with locale-dependent composite format groups
#	substituted out.
#
# Side effects:
#	None.
#
#----------------------------------------------------------------------

proc ::tcl::clock::LocalizeFormat { locale format } {


    # message catalog key to cache this format
    set key FORMAT_$format

    if { [::msgcat::mcexists -exactlocale -exactnamespace $key] } {
	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.

    set list {
	%% %%
	%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]

    ::msgcat::mcset $locale $key $format
    return $format
}

#----------------------------------------------------------------------
#
# 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.
#
#----------------------------------------------------------------------

proc ::tcl::clock::ParseStarDate { year fractYear fractDay } {
    variable Roddenberry

    # Build a tentative date from year and fraction.

    set date [dict create \
		  gregorian 1 \
		  era CE \
		  year [expr { $year + $Roddenberry }] \
		  dayOfYear [expr { $fractYear * 365 / 1000 + 1 }]]
    set date [GetJulianDayFromGregorianEraYearDay $date[set date {}]]

    # Determine whether the given year is a leap year

    set lp [IsGregorianLeapYear $date]

    # Reconvert the fractional year according to whether the given year is a
    # leap year

    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 {}]]

    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 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.
#
#----------------------------------------------------------------------

proc ::tcl::clock::AssignBaseMonth {date baseTime timezone changeover} {
    variable TZData

    # Find the year and month corresponding to the base time

    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.
#
#----------------------------------------------------------------------

proc ::tcl::clock::AssignBaseWeek {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 date iso8601Year [dict get $date2 iso8601Year]
    dict set date iso8601Week [dict get $date2 iso8601Week]
    return $date
}

#----------------------------------------------------------------------
#
# 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.
#
#----------------------------------------------------------------------

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 {
	( [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.
#
#----------------------------------------------------------------------

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





    }
    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
        }
	set CachedSystemTimeZone $timezone
    }
    if { ![dict exists $TimeZoneBad $timezone] } {
	dict set TimeZoneBad $timezone [catch {SetupTimeZone $timezone}]
    }

    if { [dict get $TimeZoneBad $timezone] } {
	return :localtime
    } else {
	return $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?
#
#----------------------------------------------------------------------

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]
}

#----------------------------------------------------------------------
#
# 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 } {
    variable TZData

    if {! [info exists TZData($timezone)] } {

	variable MINWIDE


	if { $timezone eq {:localtime} } {
	    # Nothing to do, we'll convert using the localtime function


	} elseif {
	    [regexp {^([-+])(\d\d)(?::?(\d\d)(?::?(\d\d))?)?} $timezone \
		    -> s hh mm ss]
	} then {
	    # Make a fixed offset

	    ::scan $hh %d hh
	    if { $mm eq {} } {







>
>










|
>

|
<
|
|
<
|
|
|
|
|

|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
|
<
<
<
<
<
<
|
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
|
<
|
<
|
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
















|
|




<






>
>
>
>
>
|
<
<
<
<
<
|
|
|
|
|
|
|
|
|
<


|

>
|
|
<
<

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<

<
<
<
<
<
|



















|



>
|
>
>
|
|
|
>
|







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 mcd } {
    variable LocFmtMap

    # get map list cached or build it:

    if {[dict exists $LocFmtMap $locale]} {
	set mlst [dict get $LocFmtMap $locale]

    } 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 mlst {
	    %% %%
	    %D %m/%d/%Y
	    %+ {%a %b %e %H:%M:%S %Z %Y}
	}











	lappend mlst %EY [string map $mlst [dict get $mcd LOCALE_YEAR_FORMAT]]



	lappend mlst %T  [string map $mlst [dict get $mcd TIME_FORMAT_24_SECS]]








































































































	lappend mlst %R  [string map $mlst [dict get $mcd TIME_FORMAT_24]]


	lappend mlst %r  [string map $mlst [dict get $mcd TIME_FORMAT_12]]

	lappend mlst %X  [string map $mlst [dict get $mcd TIME_FORMAT]]






	lappend mlst %EX [string map $mlst [dict get $mcd LOCALE_TIME_FORMAT]]

	lappend mlst %x  [string map $mlst [dict get $mcd DATE_FORMAT]]

	lappend mlst %Ex [string map $mlst [dict get $mcd LOCALE_DATE_FORMAT]]


	lappend mlst %c  [string map $mlst [dict get $mcd DATE_TIME_FORMAT]]










	lappend mlst %Ec [string map $mlst [dict get $mcd LOCALE_DATE_TIME_FORMAT]]



















































































































































	dict set LocFmtMap $locale $mlst


    }






















    # translate copy of format (don't use format object here, because otherwise


    # it can lose its internal representation (string map - convert to unicode)

    set locfmt [string map $mlst [string range " $format" 1 end]]




























    # Save original format as long as possible, because of internal


    # representation (performance).

    # Note that in this case such format will be never localized (also

    # using another locales). To prevent this return a duplicate (but

    # it may be slower).





    if {$locfmt eq $format} {




















	set locfmt $format







    }





















































    return $locfmt




}

#----------------------------------------------------------------------
#
# 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 system time zone in engine configuration, since
#	determining it may be an expensive process.
#
#----------------------------------------------------------------------

proc ::tcl::clock::GetSystemTimeZone {} {

    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 { $::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 { ![dict exists $TimeZoneBad $timezone] } {
	catch {set timezone [SetupTimeZone $timezone]}
    }

    if { [dict exists $TimeZoneBad $timezone] } {
	set timezone :localtime


    }

    # tell backend - current system timezone:




















    ::tcl::unsupported::clock::configure -system-tz $timezone








    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 {alias {}} } {
    variable TZData

    if {! [info exists TZData($timezone)] } {

	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 {} } {
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
	    if {
		[catch {
		    LoadTimeZoneFile [string range $timezone 1 end]
		}] && [catch {
		    LoadZoneinfoFile [string range $timezone 1 end]
		}]
	    } then {

		return -code error \
		    -errorcode [list CLOCK badTimeZone $timezone] \
		    "time zone \"$timezone\" not found"
	    }
	} elseif { ![catch {ParsePosixTimeZone $timezone} tzfields] } {
	    # This looks like a POSIX time zone - try to process it

	    if { [catch {ProcessPosixTimeZone $tzfields} data opts] } {
		if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } {
		    dict unset opts -errorinfo
		}

		return -options $opts $data
	    } else {
		set TZData($timezone) $data
	    }

	} else {



	    # 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] } {












		dict unset opts -errorinfo

		return -options $opts "time zone $timezone not found"
	    }
	    set TZData($timezone) $TZData(:$timezone)
	}
    }

    return

}

#----------------------------------------------------------------------
#
# GuessWindowsTimeZone --
#
#	Determines the system time zone on windows.







>











>






>
>
>





>
>
>
>
>
>
>
>
>
>
>
>

>






|
>







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
	    if {
		[catch {
		    LoadTimeZoneFile [string range $timezone 1 end]
		}] && [catch {
		    LoadZoneinfoFile [string range $timezone 1 end]
		}]
	    } then {
	    	dict set TimeZoneBad $timezone 1
		return -code error \
		    -errorcode [list CLOCK badTimeZone $timezone] \
		    "time zone \"$timezone\" not found"
	    }
	} elseif { ![catch {ParsePosixTimeZone $timezone} tzfields] } {
	    # This looks like a POSIX time zone - try to process it

	    if { [catch {ProcessPosixTimeZone $tzfields} data opts] } {
		if { [lindex [dict get $opts -errorcode] 0] eq {CLOCK} } {
		    dict unset opts -errorinfo
		}
		dict set TimeZoneBad $timezone 1
		return -options $opts $data
	    } else {
		set TZData($timezone) $data
	    }

	} 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] } {

		# 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
		dict set TimeZoneBad $timezone 1
		return -options $opts "time zone $timezone not found"
	    }
	    set TZData($timezone) $TZData(:$timezone)
	}
    }

    # 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
# 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] } {
	return :localtime
    }

    # Dredge time zone information out of the registry

    if { [catch {
	set rpath HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\TimeZoneInformation







<


|







1075
1076
1077
1078
1079
1080
1081

1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
# 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 TimeZoneBad

    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
    # 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}]
	}
    } else {
	set tzname {}
    }
    if { $tzname eq {} || [dict get $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 }]







|




|







1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
    # 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] } {
	    catch {set tzname [SetupTimeZone $tzname]}
	}
    } else {
	set 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 }]
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412

    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.

    binary scan $d a4a1x15IIIIII \
	magic version nIsGMT nIsStd nLeap nTime nType nChar
    set seek 44
    set ilen 4
    set iformat I
    if { $magic != {TZif} } {







|







1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326

    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 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
	([-+]?)
	# 3 - Standard time zone offset, hours
	([[:digit:]]{1,2})
	(?:
	    # 4 - Standard time zone offset, minutes
	    : ([[:digit:]]{1,2})
	    (?:
	        # 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
			    : ([[:digit:]]{1,2})
			)?
		    )?
		)?
	        (?:
		    ,
		    (?:
			# 11 - Optional J in n and Jn form 12 - Day of year
		        ( 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
			# 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) \







|







|








|




|



|
|








|











|
|








|








|

|







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
	([-+]?)
	# 3 - Standard time zone offset, hours
	([[:digit:]]{1,2})
	(?:
	    # 4 - Standard time zone offset, minutes
	    : ([[:digit:]]{1,2})
	    (?:
		# 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
			    : ([[:digit:]]{1,2})
			)?
		    )?
		)?
		(?:
		    ,
		    (?:
			# 11 - Optional J in n and Jn form 12 - Day of year
			( 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
			# 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

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 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]
	     && ( $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







|






|







1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812

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 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 $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
    } 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.
#







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1845
1846
1847
1848
1849
1850
1851





































1852
1853
1854
1855
1856
1857
1858
    } else {
	set s [lindex [::scan $s %d] 0]
    }
    set tod [expr { ( $h * 60 + $m ) * 60 + $s }]
    return [expr { $seconds + $tod }]
}






































#----------------------------------------------------------------------
#
# 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
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

    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 TimeZoneBad


    foreach p [info procs [namespace current]::scanproc'*] {
	rename $p {}
    }
    foreach p [info procs [namespace current]::formatproc'*] {

	rename $p {}
    }

    catch {unset FormatProc}
    set LocaleNumeralCache {}
    catch {unset CachedSystemTimeZone}
    set TimeZoneBad {}
    InitTZData
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

















<
<
<
<
|
<
<
<
<
<
<
<
<
<




















<
|
|


>
|
<
|
<
>
|
|
<
<
|
<



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
proc ::tcl::clock::WeekdayOnOrBefore { weekday j } {
    set k [expr { ( $weekday + 6 )  % 7 }]
    return [expr { $j - ( $j - $k ) % 7 }]
}

#----------------------------------------------------------------------
#





































































































































































































































































































































# 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} {




    ::tcl::unsupported::clock::configure -current-locale [lindex $args 0]









}

#----------------------------------------------------------------------
#
# 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 LocFmtMap
    variable mcMergedCat
    variable TimeZoneBad

    # tell backend - should invalidate:
    ::tcl::unsupported::clock::configure -clear



    # clear msgcat cache:
    set mcMergedCat [dict create]



    set LocFmtMap {}

    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
    }

    # 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
    variable domainfile \
	[file join [file dirname [info script]] effective_tld_names.txt.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







|

|







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 \
	https://publicsuffix.org/list/public_suffix_list.dat
    variable domainfile \
	[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
# 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"}} {
	    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"} {
		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"} {
		{*}$setter var $optionValue
	    }
	    return $var
	}

	method IntervalTrigger {method} {
	    # TODO: handle subclassing







|
















|






|







128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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 "\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 "\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 "\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
# cookiejar.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
#
# 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"] {
	    if {[regexp {[^-A-Za-z0-9]} $part]} {
		if {[regexp {[^-A-Za-z0-9\u00a1-\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"
		}
|








|



















|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 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 © 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 "\x2E\u3002\uFF0E\uFF61"] {
	    if {[regexp {[^-A-Za-z0-9]} $part]} {
		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
	    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"] {
	    if {[string match -nocase "xn--*" $part]} {
		set part [punydecode [string range $part 4 end]]
	    }
	    lappend parts $part
	}
	return [join $parts .]
    }







|







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 "\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
	# 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 {$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]
		}







|







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 < "\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









if {![package vsatisfies [package provide Tcl] 8.5-]} return
if {[info sharedlibextension] != ".dll"} return

package ifneeded dde 1.4.3 [list load [file join $dir tcldde14.dll] dde]









<

>
|
>
>
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12

if {[info sharedlibextension] != ".dll"} return
if {[package vsatisfies [package provide Tcl] 9.0-]} {
    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
# Encoding file: ascii, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000











|







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
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
# 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
A1












|
|







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
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
# Encoding file: cp1250, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0083201E2026202020210088203001602039015A0164017D0179
009020182019201C201D202220132014009821220161203A015B0165017E017A
00A002C702D8014100A4010400A600A700A800A9015E00AB00AC00AD00AE017B
00B000B102DB014200B400B500B600B700B80105015F00BB013D02DD013E017C
015400C100C2010200C40139010600C7010C00C9011800CB011A00CD00CE010E
01100143014700D300D4015000D600D70158016E00DA017000DC00DD016200DF
015500E100E2010300E4013A010700E7010D00E9011900EB011B00ED00EE010F
01110144014800F300F4015100F600F70159016F00FA017100FC00FD016302D9












|
|






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
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
# Encoding file: cp1251, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
04020403201A0453201E20262020202120AC203004092039040A040C040B040F
045220182019201C201D202220132014009821220459203A045A045C045B045F
00A0040E045E040800A4049000A600A7040100A9040400AB00AC00AD00AE0407
00B000B104060456049100B500B600B704512116045400BB0458040504550457
0410041104120413041404150416041704180419041A041B041C041D041E041F
0420042104220423042404250426042704280429042A042B042C042D042E042F
0430043104320433043404350436043704380439043A043B043C043D043E043F
0440044104420443044404450446044704480449044A044B044C044D044E044F













|






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
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
# Encoding file: cp1252, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030016020390152008D017D008F
009020182019201C201D20222013201402DC21220161203A0153009D017E0178
00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF
00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF
00D000D100D200D300D400D500D600D700D800D900DA00DB00DC00DD00DE00DF
00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF
00F000F100F200F300F400F500F600F700F800F900FA00FB00FC00FD00FE00FF












|
|






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
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
# Encoding file: cp1253, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202100882030008A2039008C008D008E008F
009020182019201C201D20222013201400982122009A203A009C009D009E009F
00A00385038600A300A400A500A600A700A800A9000000AB00AC00AD00AE2015
00B000B100B200B3038400B500B600B703880389038A00BB038C00BD038E038F
0390039103920393039403950396039703980399039A039B039C039D039E039F
03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF
03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF
03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000












|
|






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
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
# Encoding file: cp1254, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030016020390152008D008E008F
009020182019201C201D20222013201402DC21220161203A0153009D009E0178
00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF
00C000C100C200C300C400C500C600C700C800C900CA00CB00CC00CD00CE00CF
011E00D100D200D300D400D500D600D700D800D900DA00DB00DC0130015E00DF
00E000E100E200E300E400E500E600E700E800E900EA00EB00EC00ED00EE00EF
011F00F100F200F300F400F500F600F700F800F900FA00FB00FC0131015F00FF












|
|






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
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
# Encoding file: cp1255, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030008A2039008C008D008E008F
009020182019201C201D20222013201402DC2122009A203A009C009D009E009F
00A000A100A200A320AA00A500A600A700A800A900D700AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900F700BB00BC00BD00BE00BF
05B005B105B205B305B405B505B605B705B805B9000005BB05BC05BD05BE05BF
05C005C105C205C305F005F105F205F305F40000000000000000000000000000
05D005D105D205D305D405D505D605D705D805D905DA05DB05DC05DD05DE05DF
05E005E105E205E305E405E505E605E705E805E905EA00000000200E200F0000












|
|






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
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
# Encoding file: cp1257, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0083201E20262020202100882030008A2039008C00A802C700B8
009020182019201C201D20222013201400982122009A203A009C00AF02DB009F
00A0000000A200A300A4000000A600A700D800A9015600AB00AC00AD00AE00C6
00B000B100B200B300B400B500B600B700F800B9015700BB00BC00BD00BE00E6
0104012E0100010600C400C501180112010C00C90179011601220136012A013B
01600143014500D3014C00D500D600D701720141015A016A00DC017B017D00DF
0105012F0101010700E400E501190113010D00E9017A011701230137012B013C
01610144014600F3014D00F500F600F701730142015B016B00FC017C017E02D9












|
|






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
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
# Encoding file: cp1258, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC0081201A0192201E20262020202102C62030008A20390152008D008E008F
009020182019201C201D20222013201402DC2122009A203A0153009D009E0178
00A000A100A200A300A400A500A600A700A800A900AA00AB00AC00AD00AE00AF
00B000B100B200B300B400B500B600B700B800B900BA00BB00BC00BD00BE00BF
00C000C100C2010200C400C500C600C700C800C900CA00CB030000CD00CE00CF
011000D1030900D300D401A000D600D700D800D900DA00DB00DC01AF030300DF
00E000E100E2010300E400E500E600E700E800E900EA00EB030100ED00EE00EF
011100F1032300F300F401A100F600F700F800F900FA00FB00FC01B020AB00FF












|
|






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
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
# Encoding file: cp864, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00200021002200230024066A0026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
00B000B72219221A259225002502253C2524252C251C25342510250C25142518
03B2221E03C600B100BD00BC224800AB00BBFEF7FEF8009B009CFEFBFEFC009F
00A000ADFE8200A300A4FE8400000000FE8EFE8FFE95FE99060CFE9DFEA1FEA5
0660066106620663066406650666066706680669FED1061BFEB1FEB5FEB9061F
00A2FE80FE81FE83FE85FECAFE8BFE8DFE91FE93FE97FE9BFE9FFEA3FEA7FEA9
FEABFEADFEAFFEB3FEB7FEBBFEBFFEC1FEC5FECBFECF00A600AC00F700D7FEC9
0640FED3FED7FEDBFEDFFEE3FEE7FEEBFEEDFEEFFEF3FEBDFECCFECEFECDFEE1
FE7D0651FEE5FEE9FEECFEF0FEF2FED0FED5FEF5FEF6FEDDFED9FEF125A00000













|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Encoding file: cp864, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00200021002200230024066A0026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
00B000B72219221A259225002502253C2524252C251C25342510250C25142518
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
# Encoding file: cp869, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850386008700B700AC00A620182019038820150389
038A03AA038C00930094038E03AB00A9038F00B200B303AC00A303AD03AE03AF
03CA039003CC03CD039103920393039403950396039700BD0398039900AB00BB
25912592259325022524039A039B039C039D256325512557255D039E039F2510
25142534252C251C2500253C03A003A1255A25542569256625602550256C03A3
03A403A503A603A703A803A903B103B203B32518250C2588258403B403B52580
03B603B703B803B903BA03BB03BC03BD03BE03BF03C003C103C303C203C40384
00AD00B103C503C603C700A703C8038500B000A803C903CB03B003CE25A000A0












|
|






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
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
# Encoding file: cp874, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
20AC008100820083008420260086008700880089008A008B008C008D008E008F
009020182019201C201D20222013201400980099009A009B009C009D009E009F
00A00E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F
0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F
0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F
0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F
0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F
0E500E510E520E530E540E550E560E570E580E590E5A0E5B0000000000000000












|
|






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
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
# Encoding file: cp932, multi-byte
M
003F 0 46
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000850086000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000












|







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
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
# 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












|







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
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
# 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
A1












|
|







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
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
# Encoding file: dingbats, single-byte
S
003F 1 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00202701270227032704260E2706270727082709261B261E270C270D270E270F
2710271127122713271427152716271727182719271A271B271C271D271E271F
2720272127222723272427252726272726052729272A272B272C272D272E272F
2730273127322733273427352736273727382739273A273B273C273D273E273F
2740274127422743274427452746274727482749274A274B25CF274D25A0274F
27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000276127622763276427652766276726632666266526602460246124622463
2464246524662467246824692776277727782779277A277B277C277D277E277F
2780278127822783278427852786278727882789278A278B278C278D278E278F
2790279127922793279421922194219527982799279A279B279C279D279E279F
27A027A127A227A327A427A527A627A727A827A927AA27AB27AC27AD27AE27AF
000027B127B227B327B427B527B627B727B827B927BA27BB27BC27BD27BE0000












|
|






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
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000276127622763276427652766276726632666266526602460246124622463
2464246524662467246824692776277727782779277A277B277C277D277E277F
2780278127822783278427852786278727882789278A278B278C278D278E278F
2790279127922793279421922194219527982799279A279B279C279D279E279F
27A027A127A227A327A427A527A627A727A827A927AA27AB27AC27AD27AE27AF
000027B127B227B327B427B527B627B727B827B927BA27BB27BC27BD27BE0000

Changes to library/encoding/ebcdic.enc.


1
2
3
4
5
6
7

S
006F 0 1
00
0000000100020003008500090086007F0087008D008E000B000C000D000E000F
0010001100120013008F000A0008009700180019009C009D001C001D001E001F
0080008100820083008400920017001B00880089008A008B008C000500060007
0090009100160093009400950096000400980099009A009B00140015009E001A
>







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
# 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
A1












|
|







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
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
# 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
8E












|
|







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
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
# 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
A1












|
|







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
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
# Encoding file: gb1988, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
002000210022002300A500250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D203E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000












|
|






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
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
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
00A02018201900A30000000000A600A700A800A9000000AB00AC00AD00002015
00B000B100B200B303840385038600B703880389038A00BB038C00BD038E038F
0390039103920393039403950396039703980399039A039B039C039D039E039F
03A003A1000003A303A403A503A603A703A803A903AA03AB03AC03AD03AE03AF
03B003B103B203B303B403B503B603B703B803B903BA03BB03BC03BD03BE03BF
03C003C103C203C303C403C503C603C703C803C903CA03CB03CC03CD03CE0000







|





8
9
10
11
12
13
14
15
16
17
18
19
20
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
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
# Encoding file: jis0201, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D203E007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000












|
|






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
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
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
25002502250C251025142518251C2524252C2534253C258025842588258C2590
259125922593232025A02219221A22482264226500A0232100B000B200B700F7
25502551255204510454255404560457255725582559255A255B0491255D255E
255F25602561040104032563040604072566256725682569256A0490256C00A9
044E0430043104460434043504440433044504380439043A043B043C043D043E
043F044F044004410442044304360432044C044B04370448044D04490447044A
042E0410041104260414041504240413042504180419041A041B041C041D041E
041F042F042004210422042304160412042C042B04170428042D04290427042A







|




9
10
11
12
13
14
15
16
17
18
19
20
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
25002502250C251025142518251C2524252C2534253C258025842588258C2590
259125922593232025A02219221A22482264226500A0232100B000B200B700F7
25502551255204510454255404560457255725582559255A255B0491255D255E
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
# Encoding file: macDingbats, single-byte
S
003F 1 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00202701270227032704260E2706270727082709261B261E270C270D270E270F
2710271127122713271427152716271727182719271A271B271C271D271E271F
2720272127222723272427252726272726052729272A272B272C272D272E272F
2730273127322733273427352736273727382739273A273B273C273D273E273F
2740274127422743274427452746274727482749274A274B25CF274D25A0274F
27502751275225B225BC25C6275625D727582759275A275B275C275D275E007F
F8D7F8D8F8D9F8DAF8DBF8DCF8DDF8DEF8DFF8E0F8E1F8E2F8E3F8E4008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
0000276127622763276427652766276726632666266526602460246124622463
2464246524662467246824692776277727782779277A277B277C277D277E277F
2780278127822783278427852786278727882789278A278B278C278D278E278F
2790279127922793279421922194219527982799279A279B279C279D279E279F
27A027A127A227A327A427A527A627A727A827A927AA27AB27AC27AD27AE27AF
000027B127B227B327B427B527B627B727B827B927BA27BB27BC27BD27BE0000












|
|






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
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
# Encoding file: macJapan, multi-byte
M
003F 0 46
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00A0FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000A921222026












|







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
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
# Encoding file: shiftjis, multi-byte
M
003F 0 40
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
0080000000000000000000850086008700000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
0000FF61FF62FF63FF64FF65FF66FF67FF68FF69FF6AFF6BFF6CFF6DFF6EFF6F
FF70FF71FF72FF73FF74FF75FF76FF77FF78FF79FF7AFF7BFF7CFF7DFF7EFF7F
FF80FF81FF82FF83FF84FF85FF86FF87FF88FF89FF8AFF8BFF8CFF8DFF8EFF8F
FF90FF91FF92FF93FF94FF95FF96FF97FF98FF99FF9AFF9BFF9CFF9DFF9EFF9F
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000












|







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
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
# Encoding file: symbol, single-byte
S
003F 1 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002122000023220300250026220D002800292217002B002C2212002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
22450391039203A70394039503A603930397039903D1039A039B039C039D039F
03A0039803A103A303A403A503C203A9039E03A80396005B2234005D22A5005F
F8E503B103B203C703B403B503C603B303B703B903D503BA03BB03BC03BD03BF
03C003B803C103C303C403C503D603C903BE03C803B6007B007C007D223C007F
0080008100820083008400850086008700880089008A008B008C008D008E008F
0090009100920093009400950096009700980099009A009B009C009D009E009F
000003D2203222642044221E0192266326662665266021942190219121922193
00B000B12033226500D7221D2202202200F72260226122482026F8E6F8E721B5
21352111211C21182297229522052229222A2283228722842282228622082209
2220220700AE00A92122220F221A22C500AC2227222821D421D021D121D221D3
22C42329F8E8F8E9F8EA2211F8EBF8ECF8EDF8EEF8EFF8F0F8F1F8F2F8F3F8F4
F8FF232A222B2320F8F52321F8F6F8F7F8F8F8F9F8FAF8FBF8FCF8FDF8FE0000












|
|






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
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
# Encoding file: tis-620, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
0020002100220023002400250026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E0000
0000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
00000E010E020E030E040E050E060E070E080E090E0A0E0B0E0C0E0D0E0E0E0F
0E100E110E120E130E140E150E160E170E180E190E1A0E1B0E1C0E1D0E1E0E1F
0E200E210E220E230E240E250E260E270E280E290E2A0E2B0E2C0E2D0E2E0E2F
0E300E310E320E330E340E350E360E370E380E390E3A00000000000000000E3F
0E400E410E420E430E440E450E460E470E480E490E4A0E4B0E4C0E4D0E4E0E4F











|







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
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
# history.tcl --
#
# Implementation of the history command.
#
# 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.
#

# The tcl::history array holds the history list and some additional
# bookkeeping variables.




|







1
2
3
4
5
6
7
8
9
10
11
12
# history.tcl --
#
# Implementation of the history command.
#
# 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
    # 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
}

# (unnamed) --
#
#	Callback when [::history] is destroyed. Destroys the implementation.
#
# Parameters:







|







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 ::tcl::history {*}$arglist} ::tcl} $args
}

# (unnamed) --
#
#	Callback when [::history] is destroyed. Destroys the implementation.
#
# Parameters:
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 $i
}

# tcl::HistEvent --
#
#	Map from an event specifier to the value in the history list.







|







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 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
# 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

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


	    -repost 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













|














>
>

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.10b2

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

	# Create a map for HTTP/1.1 open sockets
	variable socketMapping
	variable socketRdState
	variable socketWrState
	variable socketRdQueue
	variable socketWrQueue

	variable socketClosing
	variable socketPlayCmd


	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 socketClosing
	array unset socketPlayCmd


	array set socketMapping {}
	array set socketRdState {}
	array set socketWrState {}
	array set socketRdQueue {}
	array set socketWrQueue {}

	array set socketClosing {}
	array set socketPlayCmd {}



    }
    init

    variable urlTypes
    if {![info exists urlTypes]} {
	set urlTypes(http) [list 80 ::socket]
    }

    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"







>


>
>




















>


>
>





>


>
>
>





|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
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 ::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
	([!\u0023-+\u002D-:<-\u005B\u005D-~]*)         # Match the value
	(?:
	 \s* ; \s*                                     # LITERAL: semicolon
	 ([^\u0000]+)                                  # Match the options
	)?
    }

































































































    namespace export geturl config reset wait formatQuery quoteString
    namespace export register unregister registerError






    # - 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.
}

# 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






# Results:

#     list of port and command that was registered.

proc http::register {proto port command} {
    variable urlTypes
    set urlTypes([string tolower $proto]) [list $port $command]












}

# http::unregister --
#
#     Unregisters URL protocol handler
#
# Arguments:
#     proto	URL protocol prefix, e.g. https
# Results:

#     list of port and command 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)







    unset urlTypes($lower)
    return $old
}

# http::config --
#
#	See documentation for details.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
|
>
>
>
|
|
|
|

















|
|
|
>
>
>
>
>
>

>
|

|

|
>
>
>
>
>
>
>
>
>
>
>
>









>
|








>
>
>
>
>
>
>







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
	([!\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 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
    #   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
#     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,
#     and (boolean) endToEndProxy that was registered.

proc http::register {proto port command {socketCmdVarName {}} {useSockThread 0} {endToEndProxy 0}} {
    variable urlTypes
    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,
#     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.
219
220
221
222
223
224
225



226
227
228
229
230



231
232

233
234



























235
236
237
238
239
240
241
    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)



    } else {
	foreach {flag value} $args {
	    if {![regexp -- $pat $flag]} {
		return -code error "Unknown option $flag, must be: $usage"
	    }



	    set http($flag) $value
	}

    }
}




























# http::Finish --
#
#	Clean up the socket and eval close time callbacks
#
# Arguments:
#	token	    Connection token.







>
>
>





>
>
>


>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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 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.
250
251
252
253
254
255
256

257
258


259
260
261
262
263
264
265
266
267
268
269
270





















271
272
273






























274
275
276
277
278

279
280





281
282
283
284
285
286
287
288
289
290
291
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

proc http::Finish {token {errormsg ""} {skipCB 0}} {
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue

    variable socketClosing
    variable socketPlayCmd



    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 {  ($state(status) eq "timeout")
       || ($state(status) eq "error")
       || ($state(status) eq "eof")






























       || ([info exists state(-keepalive)] && !$state(-keepalive))
       || ([info exists state(connection)] && ($state(connection) eq "close"))
    } {
	set closeQueue 1
	set connId $state(socketinfo)

	set sock $state(sock)
	CloseSocket $state(sock) $token





    } elseif {
	  ([info exists state(-keepalive)] && $state(-keepalive))
       && ([info exists state(connection)] && ($state(connection) ne "close"))
    } {
	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 {eval $state(-command) {$token}} err] && $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

    }

}

# 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
#	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 socketClosing
    variable socketPlayCmd



    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.







>


>
>









|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|



>
|
|
>
>
>
>
>


|










>
|
>










>

>








|












>


>
>







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

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}--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 {}}
    } 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
	} 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)] && ("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]
	     && ($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 ("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
	     && [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







<
<
<







602
603
604
605
606
607
608



609
610
611
612
613
614
615
	     && [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]




	    #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
	    #   "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)]
	    #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)







<
|







640
641
642
643
644
645
646

647
648
649
650
651
652
653
654
	    #   "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.

	    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
	    # 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)]
	    #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")
	} {
	    # 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)]
	    #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.
    }

}

# 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







<
|












|







<
|


















>







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
	    # 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.

	    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)]
	     && ("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]

	    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

    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
    }

}

# 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 socketClosing
    variable socketPlayCmd



    set tk [namespace tail $token]

    catch {fileevent $s readable {}}
    set connId {}
    if {$token ne ""} {
	variable $token







>















>


>
>







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

    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
    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"

	}
	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 {
	Log "Closing socket $s (no connection info)"
	if {[catch {close $s} err]} {
	    Log "Error closing socket: $err"

	}
    }

}

# 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 socketClosing
    variable socketPlayCmd




    if {![info exists socketMapping($connId)]} {
	# Command has already been called.
	# Don't come here again - especially recursively.
	return
    }

    # Used only for logging.







>





>





>


>
















>


>
>

>







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
    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
	# 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".

	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
	{*}$unfinished

    }

}

# 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 socketClosing
    variable socketPlayCmd



    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)


}

# http::reset --
#
#	See documentation for details.
#
# Arguments:







>











|

>

>















>


>
>








>
>







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
	# 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 - 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:
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
    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

    }

}

# 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 http
    variable urlTypes
    variable defaultCharset
    variable defaultKeepalive
    variable strict


    # Initialize the state variable, an array. We'll return the name of this
    # array as the token for the transaction.




    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







>

>















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>




>
>
>







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
    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
	-queryblocksize 8192
	-validate	0
	-headers	{}
	-timeout	0
	-type		application/x-www-form-urlencoded
	-queryprogress	{}
	-protocol	1.1

	binary		0
	state		created
	meta		{}
	method		{}
	coding		{}
	currentsize	0
	totalsize	0
	querylength	0
	queryoffset	0
	type		text/html
	body		{}
	status		""
	http		""



	connection	keep-alive







    }
    set state(-keepalive) $defaultKeepalive
    set state(-strict) $strict
    # These flags have their types verified [Bug 811170]
    array set type {
	-binary		boolean
	-blocksize	integer

	-queryblocksize integer
	-strict		boolean
	-timeout	integer
	-validate	boolean
	-headers	dict
    }
    set state(charset)	$defaultCharset
    set options {
	-binary -blocksize -channel -command -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])
	    } {
		unset $token
		return -code error \
		    "Bad value for $flag ($value), must be $type($flag)"





	    }
	    set state($flag) $value
	} else {
	    unset $token
	    return -code error "Unknown option $flag, can be: $usage"
	}
    }







>









|



>
>
>

>
>
>
>
>
>
>







>




|



|









|
|




>
>
>
>
>







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
	-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		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	list
    }
    set state(charset)	$defaultCharset
    set options {
	-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 {    [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
    # 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.



    #
    # 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
	^







>
>
>







1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
    # 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
	set proto http
    }
    set lower [string tolower $proto]
    if {![info exists urlTypes($lower)]} {
	unset $token
	return -code error "Unsupported URL type \"$proto\""
    }

    set defport [lindex $urlTypes($lower) 0]





    set defcmd [lindex $urlTypes($lower) 1]



    if {$port eq ""} {
	set port $defport
    }
    if {![catch {$http(-proxyfilter) $host} proxy]} {
	set phost [lindex $proxy 0]
	set pport [lindex $proxy 1]



    }

    # 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!
    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)











    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
	}





    } else {
	# It's a 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
    }



































    # 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

    if {$state(-keepalive)} {
	variable socketMapping
	variable socketRdState
	variable socketWrState
	variable socketRdQueue
	variable socketWrQueue

	variable socketClosing
	variable socketPlayCmd



	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),







>
|
>
>
>
>
>
|
>
>







>
>
>













|


<
<
<
<
<
<
<
<
<
<
<







>
>
>
>
>
>
>
>
>
>















>
>
>
>
>

|















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|
>






>


>
>







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
	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

    # 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! RFC 7230 Sec 5.1
    set state(url) $url












    # 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 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 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
		# 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))

		Log "reusing socket $sock for $state(socketinfo) - token $token"

		set 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



	    } elseif {[catch {fconfigure $socketMapping($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.

		set reusing 1
		set sock $socketMapping($state(socketinfo))



		Log "reusing 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

    # 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

































    # 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 {![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
	##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







	    # 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












	} else {










	    # 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)



	    ##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
    # 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" \
	[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)) {}

	    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 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
	}













	set socketRdQueue($state(socketinfo)) {}
	set socketWrQueue($state(socketinfo)) {}


	set socketClosing($state(socketinfo)) 0


	set socketPlayCmd($state(socketinfo)) {ReplayIfClose Wready {} {}}
    }

    if {![info exists phost]} {
	set phost ""








    }
    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.










































    if {$alreadyQueued} {



	# 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"








>
|

|




>
>
>
|
>
>
>













|
|
|
|
>


>
>
>
|
>
|
>






<
<
<
<
<
<
<
<
<
<
<
<
<

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
|
>
>
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>









>
>
>

|
|
>
>
|
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
|
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
|
|
>
>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>


|
|
<


|
|
|
>
|
|
>
>
|
|
|
>
|
>
>
>
>
|
<
>
>
>
>
>
>
|
>
|
|
>
>
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
>
>
|
<
|
<
<
>
>
>
>
>
>
>
>
|
<
<
<
<
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>







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
		# 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 closing socket $sock for $state(socketinfo) - token $token"

		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 {
		   [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 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
		    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
	}
    }














    set state(reusing) $reusing
    unset reusing

    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 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))   {}
    }
    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
}

# ------------------------------------------------------------------------------
#  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
        }

        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.

	# 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
}



# ------------------------------------------------------------------------------
#  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 {[dict get $DoLater -tracewrite]} {

	    set varName ::http::socketWrState($state(socketinfo))
	    trace add variable $varName unset ::http::CancelWritePipeline
        }
    }

    # 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


	    # 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.


# 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.
# ------------------------------------------------------------------------------






# ------------------------------------------------------------------------------
# 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 {$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
	       && ($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


	    set socketWrState($state(socketinfo)) $token

	} elseif {$reusing} {

	    # Cf tests above - both are ready.


	    #Log re-use nonpipeline, GRANT r/w access to $token in geturl
	    set socketRdState($state(socketinfo)) $token
	    set socketWrState($state(socketinfo)) $token

	}




	# All (!$reusing) cases come here, and also some $reusing cases if the

	# connection is ready.




	#Log ---- $state(socketinfo) << conn to $token for HTTP request (a)

	# Connect does its own fconfigure.




	fileevent $sock writable \
		[list http::Connect $token $proto $phost $srvurl]



    }

    # 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"} {
	    # 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
}

# http::Connected --
#
#	Callback used when the connection to the HTTP server is actually
#	established.
#







<




|
|
>
>
|
<
|
>
|
>
>
|
|
|
>
|

>
>
>
|
>
|
>
>
>
>

>

>
>
>
>
|
|
>
>
>
|

<
<
<
<
<
|
|
<
<
<
|
>
|
<
<
<
<
<
<
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
|







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
	       && ($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 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.
	    # 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.
	# - 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 $state(sock) writable \
			[list http::Connect $token $proto $phost $srvurl]
	} res opts]} {
	    # The socket no longer exists.
	    ##Log bug -- socket gone -- $res -- $opts
	}






    }




    return
}









# ------------------------------------------------------------------------------
#  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
    variable http
    variable urlTypes
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue

    variable socketClosing
    variable socketPlayCmd



    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]
    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)




    # 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} {







>


>
>














|
<










>
>
>







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
    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)]
    regexp {^(.+):([^:]+)$} $state(socketinfo) {} host port


    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
	set how $state(-method)
    }
    set accept_types_seen 0

    Log ^B$tk begin sending request - token $token

    if {[catch {





	set state(method) $how

	puts $sock "$how $srvurl HTTP/$state(-protocol)"


	if {[dict exists $state(-headers) Host]} {

	    # Allow Host spoofing. [Bug 928154]
	    set hostHdr [dict get $state(-headers) Host]
	    regexp {^[^:]+} $hostHdr state(host)
	    puts $sock "Host: $hostHdr"
	} elseif {$port == $defport} {
	    # Don't add port in this case, to handle broken servers. [Bug
	    # #504508]
	    set state(host) $host
	    puts $sock "Host: $host"
	} else {
	    set state(host) $host
	    puts $sock "Host: $host:$port"
	}
	puts $sock "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"
	}
	if {($state(-protocol) > 1.0) && !$state(-keepalive)} {
	    puts $sock "Connection: close" ;# RFC2616 sec 8.1.2.1

	}
	if {($state(-protocol) < 1.1)} {
	    # 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"
	}





	# 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

	dict for {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 length $key]} {
		puts $sock "$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)"
	}
	if {    (!$accept_encoding_seen)
	     && (![info exists state(-handler)])
	     && $http(-zip)
	} {


	    puts $sock "Accept-Encoding: gzip,deflate,compress"




	}
	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







>
>
>
>
>
|
>
|
>
>
|
>

<
|
|




|


|

|



|
<
|
|
>
|
|






|

>
>
>
>
>




>
|


















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|





|





>
>
|
>
>
>
>







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
	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
	    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]

	    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
	    SendHeader $token Host $host
	} else {
	    set state(host) $host
	    SendHeader $token Host "$host:$port"
	}
	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.
	    set ConnVal keep-alive

	} 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".
	    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
	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]} {
		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} {
	    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} {
	    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
	    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"
	    }
	}

	# Flush the request header and set up the fileevent that will either
	# push the POST data or read the response.
	#
	# fileevent note:







|







2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
	    set separator ""
	    foreach {key value} [{*}$http(-cookiejar) \
		    getCookies $proto $host $state(path)] {
		append cookies $separator $key = $value
		set separator "; "
	    }
	    if {$cookies ne ""} {
		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
	# 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)"
	    }
	    if {!$contDone} {
		puts $sock "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).








|


|







2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
	# 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} {
		SendHeader $token Content-Type $state(-type)
	    }
	    if {!$contDone} {
		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).

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

	    # 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.

	    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
	}
    }

}

# 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







|
>










>







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

	    # 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, 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
proc http::DoneRequest {token} {
    variable http
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue

    variable socketClosing
    variable socketPlayCmd



    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.







>


>
>







2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
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
	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
    }

}

# 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)



    Log ^D$tk begin receiving response - token $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]
    } else {
        fileevent $sock readable ${token}EventCoroutine
    }
    return
}


# http::EventGateway
#







>
















>
>
>


|



|







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
	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
    if {[info exists state(-handler)] || [info exists state(-progress)]} {
        fileevent $sock readable [list http::EventGateway $sock $token]
    } else {
        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
#	  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]}
    }

    # If there was an error, re-throw it.
    return -options $opts $res







|
|





|







2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
#	  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::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
	 && ([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 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.







|







2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
	 && ([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}(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

	       && [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)]
	#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)







<
<
|







2722
2723
2724
2725
2726
2727
2728


2729
2730
2731
2732
2733
2734
2735
2736

	       && [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.


	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
	# - 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
    }

}

# http::CancelReadPipeline
#
#	Cancel pipelined responses on a closing "Keep-Alive" socket.
#
#	- Called by a variable trace on "unset socketRdState($connId)".







>







2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
	# - 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
	    set tk [namespace tail $token]
	    Log ^X$tk end of response "($msg)" - token $token
	    set ${token}(status) eof
	    Finish $token ;#$msg
	}
	set socketRdQueue($connId) {}
    }

}

# http::CancelWritePipeline
#
#	Cancel queued events on a closing "Keep-Alive" socket.
#
#	- Called by a variable trace on "unset socketWrState($connId)".







>







2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
	    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
	    set tk [namespace tail $token]
	    Log ^X$tk end of response "($msg)" - token $token
	    set ${token}(status) eof
	    Finish $token ;#$msg
	}
	set socketWrQueue($connId) {}
    }

}

# 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.







>







2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
	    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
#
# Arguments:
#	token	Connection token.
#
# Side Effects:
#	Use the same token, but try to open a new socket.

proc http::ReplayIfDead {tokenArg doing} {
    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue

    variable socketClosing
    variable socketPlayCmd



    variable $tokenArg
    upvar 0 $tokenArg stateArg

    Log running http::ReplayIfDead for $tokenArg $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)} {
	# 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")
	} {
	    lappend InFlightR $socketRdState($stateArg(socketinfo))
	} elseif {($doing eq "read")} {
	    lappend InFlightR $tokenArg
	}

	if {    [info exists socketWrState($stateArg(socketinfo))]
	     && $socketWrState($stateArg(socketinfo)) ni {Wready peNding}
	} {
	    lappend InFlightW $socketWrState($stateArg(socketinfo))
	} elseif {($doing eq "write")} {
	    lappend InFlightW $tokenArg
	}

	# Report any inconsistency of $tokenArg with socket*state.
	if {    ($doing eq "read")
	     && [info exists socketRdState($stateArg(socketinfo))]
	     && ($tokenArg ne $socketRdState($stateArg(socketinfo)))
	} {
	    Log WARNING - ReplayIfDead pipelined tokenArg $tokenArg $doing \
		    ne socketRdState($stateArg(socketinfo)) \
		      $socketRdState($stateArg(socketinfo))

	} elseif {
		($doing eq "write")
	     && [info exists socketWrState($stateArg(socketinfo))]
	     && ($tokenArg ne $socketWrState($stateArg(socketinfo)))
	} {
	    Log WARNING - ReplayIfDead pipelined tokenArg $tokenArg $doing \
		    ne socketWrState($stateArg(socketinfo)) \
		      $socketWrState($stateArg(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 the inconsistency that socketRdQueue is non-empty.
	if {    [info exists socketRdQueue($stateArg(socketinfo))]
	     && ($socketRdQueue($stateArg(socketinfo)) ne {})
	} {
	    Log WARNING - ReplayIfDead nonpipeline tokenArg $tokenArg $doing \
		    has read queue socketRdQueue($stateArg(socketinfo)) \
		    $socketRdQueue($stateArg(socketinfo)) ne {}
	}

	lappend InFlightW $socketRdState($stateArg(socketinfo))
	set socketRdQueue($stateArg(socketinfo)) {}
    }

    set newQueue {}
    lappend newQueue {*}$InFlightR
    lappend newQueue {*}$socketRdQueue($stateArg(socketinfo))
    lappend newQueue {*}$InFlightW
    lappend newQueue {*}$socketWrQueue($stateArg(socketinfo))


    # 2. Tidy up tokenArg.  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
    #    ReplayCore/ReInit, or Finish is called.

    catch {close $stateArg(sock)}


    # 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

}

# 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







|





>


>
>

|
|

|








|






|
|

|

|


|
|

|

|


|

|
|

|
|
|



|
|

|
|
|






|
|
|
|
|



|
|

|
|
|


|
|




|

|


|

|


|
>











>







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
#
# Arguments:
#	token	Connection token.
#
# Side Effects:
#	Use the same token, but try to open a new socket.

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 $token
    upvar 0 $token state

    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 {$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($state(socketinfo))]
	     && ($socketRdState($state(socketinfo)) ne "Rready")
	} {
	    lappend InFlightR $socketRdState($state(socketinfo))
	} elseif {($doing eq "read")} {
	    lappend InFlightR $token
	}

	if {    [info exists socketWrState($state(socketinfo))]
	     && $socketWrState($state(socketinfo)) ni {Wready peNding}
	} {
	    lappend InFlightW $socketWrState($state(socketinfo))
	} elseif {($doing eq "write")} {
	    lappend InFlightW $token
	}

	# Report any inconsistency of $token with socket*state.
	if {    ($doing eq "read")
	     && [info exists socketRdState($state(socketinfo))]
	     && ($token ne $socketRdState($state(socketinfo)))
	} {
	    Log WARNING - ReplayIfDead pipelined token $token $doing \
		    ne socketRdState($state(socketinfo)) \
		      $socketRdState($state(socketinfo))

	} elseif {
		($doing eq "write")
	     && [info exists socketWrState($state(socketinfo))]
	     && ($token ne $socketWrState($state(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 $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($state(socketinfo))]
	     && ($socketRdQueue($state(socketinfo)) ne {})
	} {
	    Log WARNING - ReplayIfDead nonpipeline token $token $doing \
		    has read queue socketRdQueue($state(socketinfo)) \
		    $socketRdQueue($state(socketinfo)) ne {}
	}

	lappend InFlightW $socketRdState($state(socketinfo))
	set socketRdQueue($state(socketinfo)) {}
    }

    set newQueue {}
    lappend newQueue {*}$InFlightR
    lappend newQueue {*}$socketRdQueue($state(socketinfo))
    lappend newQueue {*}$InFlightW
    lappend newQueue {*}$socketWrQueue($state(socketinfo))


    # 2. Tidy up token.  This is a cut-down form of Finish/CloseSocket.
    #    Do not change state(status).
    #    No need to after cancel state(after) - either this is done in
    #    ReplayCore/ReInit, or Finish is called.

    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
    }

    # 1. Create newQueue
    set InFlightW {}
    if {$Wstate ni {Wready peNding}} {
	lappend InFlightW $Wstate
    }

    set newQueue {}
    lappend newQueue {*}$Rqueue
    lappend newQueue {*}$InFlightW
    lappend newQueue {*}$Wqueue

    # 2. Cleanup - none needed, done by the caller.

    ReplayCore $newQueue

}

# http::ReInit --
#
#	Command to restore a token's state to a condition that
#	makes it ready to replay a request.
#







|








>







2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
    }

    # 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
	return 0
    }

    if {[info exists state(after)]} {
	after cancel $state(after)
	unset state(after)
    }






    # 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"} {







>
>
>
>
>







3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
	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
# Arguments:
#	newQueue	List of connection tokens.
#
# Side Effects:
#	Use existing tokens, but try to open a new socket.

proc http::ReplayCore {newQueue} {


    variable socketMapping
    variable socketRdState
    variable socketWrState
    variable socketRdQueue
    variable socketWrQueue

    variable socketClosing
    variable socketPlayCmd



    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

	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(after) [after $state(-timeout) $resetCmd]
    }

    set pre [clock milliseconds]
    ##Log pre socket opened, - token $token
    ##Log $tmpOpenCmd - token $token
    # 4. Open a socket.
    if {[catch {eval $tmpOpenCmd} sock]} {
	# Something went wrong while trying to establish the connection.
	Log FAILED - $sock
	set state(sock) NONE
	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).

    # 5. Configure the persistent socket data.
    if {$state(-keepalive)} {
	set socketMapping($state(socketinfo)) $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


	} else {

	    set ${tok}(reusing) 1
	    set ${tok}(sock) NONE
	    Finish $token {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" \
	[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

    # 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} {
    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} {
    variable $token
    upvar 0 $token state
    return $state(http)
}
proc http::ncode {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::meta {token} {
    variable $token
    upvar 0 $token state













    return $state(meta)

























































































}
proc http::error {token} {
    variable $token
    upvar 0 $token state
    if {[info exists state(error)]} {
	return $state(error)
    }
    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

proc http::cleanup {token} {
    variable $token
    upvar 0 $token state
    if {[info commands ${token}EventCoroutine] ne {}} {
	rename ${token}EventCoroutine {}



    }
    if {[info exists state(after)]} {
	after cancel $state(after)
	unset state(after)
    }





    if {[info exists state]} {
	unset state
    }

}

# http::Connect
#
#	This callback is made when an asyncronous connection completes.
#
# Arguments
#	token	The token returned from http::geturl
#
# Side Effects
#	Sets the status of the connection, which unblocks
# 	the waiting geturl call

proc http::Connect {token proto phost srvurl} {
    variable $token
    upvar 0 $token state
    set tk [namespace tail $token]


    set err "due to unexpected EOF"
    if {
	[eof $state(sock)] ||
	[set err [fconfigure $state(sock) -error]] ne ""

    } {








	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 {
	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 socketClosing
    variable socketPlayCmd



    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







>
>





>


>
>



















>












|
|
|
<
|
|
<
<
<
|
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




>
>

>


|



<
<
|
<

<
<
<
<
|
<
<
<








|












|




|
>
>
>
>
>













>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|
>
>
>
>
>
>
>
>










|




|
|
>
>
>





>
>
>
>
>



>




|












>
>
|
<
<
|
>
|
>
>
>
>
>
>
>
>















|
|
<
<
<
<



















>


>
>







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
# 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
    set state(ReusingPlaceholder) 0
    set state(alreadyQueued) 0
    Log ReplayCore replay $token


    # Give the socket a placeholder name before it is created.



    set sock HTTP_PLACEHOLDER_[incr TmpSockCounter]



    set state(sock) $sock













    # Move the $newQueue into the placeholder socket's socketPhQueue.



    set socketPhQueue($sock) {}






























    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 $tok {cannot send this request again}
	}
    }



    AsyncTransaction $token






    return



}

# 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::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::responseLine {token} {
    variable $token
    upvar 0 $token state
    return $state(http)
}
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 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($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
}
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.

proc http::cleanup {token} {
    variable $token
    upvar 0 $token state
    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 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

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"


    } 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"
    return




}

# 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
	    }
	    puts -nonewline $sock $outStr
	    incr state(queryoffset) [string length $outStr]
	    if {[eof $state(-querychannel)]} {
		set done 1
	    }
	}
    } err]} {
	# 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 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) \
	    [list $token $state(querylength) $state(queryoffset)]
    }

}

# http::Event
#
#	Handle input on the socket. This command is the core of
#	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 socketClosing
    variable socketPlayCmd



    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 {[set d [read $sock]] ne ""} {
		    Log "WARNING: additional data left on closed socket\
			    - token $token"

		}

	    }
	    Log ^X$tk end of response (token error) - token $token
	    CloseSocket $sock
	    return

	}
	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]]

	    }

	    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:
		    # 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 {







		    Log ^X$tk end of response (error) - token $token
		    Finish $token $nsl
		    return
		}
	    } elseif {$nsl >= 0} {
		##Log - connecting 1 - token $token
		set state(state) "header"
	    } elseif {    [eof $sock]
		       && [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:
		# 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(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.














		}

		if {    ([info exists state(connection)])
		     && ([info exists socketMapping($state(socketinfo))])
		     && ($state(connection) eq "keep-alive")
		     && ($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

		}

		# 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")
		     && ($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.















		    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 {
			set socketPlayCmd($state(socketinfo)) \
				{ReplayIfClose Wready {} {}}
		    }

		    # Do not allow further connections on this socket.

		    set socketClosing($state(socketinfo)) 1

		}

		set state(state) body















		# 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








































		}

		# - 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")
			  )
			)
		     && (![info exists state(transfer)])
		     && ($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

		}

		# 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

		}
		if {[info exists state(-channel)]} {
		    if {$state(binary) || [llength [ContentEncoding $token]]} {
			fconfigure $state(-channel) -translation binary

		    }
		    if {![info exists state(-handler)]} {
			# Initiate a sequence of background fcopies.
			fileevent $sock readable {}
			rename ${token}EventCoroutine {}
			CopyStart $sock $token
			return

		    }

		}
	    } elseif {$nhl > 0} {
		# Process header lines.
		##Log header - token $token - $line
		if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} {
		    switch -- [string tolower $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]







|


<

>
>
>















|


>





|
















>


>
>










|



>

>




>










>











|
|






>
>
>
>
>
>
>

|





|









>







>


















>
>
>
>
>
>
>
>
>
>
>
>
>
>




|










>











|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












<














|
|
>
>
|





|
>

>



>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















|


|









>











>




>




|


>

>





|
>







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
	    }
	    puts -nonewline $sock $outStr
	    incr state(queryoffset) [string length $outStr]
	    if {[eof $state(-querychannel)]} {
		set done 1
	    }
	}
    } 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)]} {
	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
#	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 {!([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 $msg
		    return
		}
	    } elseif {$nsl >= 0} {
		##Log - connecting 1 - token $token
		set state(state) "header"
	    } 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))])
		     && ("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))])
		     && ("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 (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)]
			    && ("close" in $state(connection))
			  )
			)
		     && ($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 {}
			CopyStart $sock $token
			return
		    } else {
		    }
		} else {
		}
	    } elseif {$nhl > 0} {
		# Process header lines.
		##Log header - token $token - $line
		if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} {
		    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
			}
			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
			    # 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
			    } else {
				set tmpResult keep-alive
				set tmpCsl [split $tmpHeader ,]
				# Optional whitespace either side of separator.
				foreach el $tmpCsl {
				    if {[string trim $el] eq {close}} {
					set tmpResult close
					break
				    }


			        }
				set tmpHeader $tmpResult
			    }

			    set state(connection) $tmpHeader
			}
			set-cookie {
			    if {$http(-cookiejar) ne ""} {
				ParseCookie $token [string trim $value]

			    }
			}
		    }
		    lappend state(meta) $key [string trim $value]

		}

	    }
	} else {
	    # Now reading body
	    ##Log body - token $token
	    if {[catch {
		if {[info exists state(-handler)]} {
		    set n [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

		    }
		    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\







<

|
>
|
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
|
<
|
>
>
|
<
|
>
|




>




>

>






|








>







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
			}
			transfer-encoding {
			    set state(transfer) \
				    [string trim [string tolower $value]]
			}
			proxy-connection -
			connection {

			    # RFC 7230 Section 6.1 states that a comma-separated
			    # list is an acceptable value.
			    if {![info exists state(connectionRespFlag)]} {
				# This is the first "Connection" response header.








				# Scrub the earlier value set by iniitialisation.

				set state(connectionRespFlag) {}




				set state(connection) {}

			    }
			    foreach el [SplitCommaSeparatedFieldValue $value] {
				lappend state(connection) [string tolower $el]
			    }

			}
			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 [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
			    #     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
			}

		    }
		} elseif {[info exists state(transfer_final)]} {
		    # This code forgives EOF in place of the final CRLF.
		    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







>



|







3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
			    #     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 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
			Eot $token
		    }
		} elseif {    [info exists state(transfer)]
			   && ($state(transfer) eq "chunked")
		} {
		    ##Log chunked - token $token
		    set size 0
		    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

			    }
			    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

			    }
			    # CRLF that follows chunk.
			    # If eof, this is handled at the end of this proc.
			    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







|












>












>



|







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
			Eot $token
		    }
		} elseif {    [info exists state(transfer)]
			   && ($state(transfer) eq "chunked")
		} {
		    ##Log chunked - token $token
		    set size 0
		    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
			} 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
			    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

		    }
		}
		# 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

		    }
		    # 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

		    }

		}
	    } err]} {
		Log ^X$tk end of response (error ${err}) - token $token
		Finish $token $err
		return
	    } else {
		if {[info exists state(-progress)]} {
		    eval $state(-progress) \
			[list $token $state(totalsize) $state(currentsize)]

		}
	    }
	}

	# 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} {

	    ##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







>











>










>

>







|

>






|
>







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
			    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)]} {
		    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 {(![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
		    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

	}
    }

}

# 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.







|
|
>


>







4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
		    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
	    }
	} 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
	}
    }
    dict set realopts key $cookiename
    dict set realopts value $cookieval
    {*}$http(-cookiejar) storeCookie $realopts
}

# http::getTextLine --
#
#	Get one line with the stream in crlf mode.
#	Used if Transfer-Encoding is chunked.

#	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} {
    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.



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]
	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]
	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
    if {[info exists state(transfer)] && $state(transfer) eq "chunked"} {
	foreach coding [ContentEncoding $token] {






	    lappend state(zlib) [zlib stream $coding]
	}
	make-transformation-chunked $sock [namespace code [list CopyChunk $token]]
    } else {
	if {$initial} {
	    foreach coding [ContentEncoding $token] {






		zlib push $coding $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
	}
    }

}

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 \
		      $token $state(totalsize) $state(currentsize)]
	}
    } else {
	Log "CopyChunk Finish - token $token"
	if {[info exists state(zlib)]} {
	    set excess ""
	    foreach stream $state(zlib) {

		catch {set excess [$stream add -finalize $excess]}




	    }
	    puts -nonewline $state(-channel) $excess
	    foreach stream $state(zlib) { $stream close }
	    unset state(zlib)
	}
	Eot $token ;# FIX ME: pipelining.
    }

}

# http::CopyDone
#
#	fcopy completion callback
#
# Arguments
#	token	The token returned from http::geturl
#	count	The amount transfered
#
# 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) \
	    [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
    }

}

# http::Eot
#
#	Called when either:
#	a. An eof condition is detected on the socket.
#	b. The client decides that the response is complete.







|


|
>









|












>
>









|



















|




















|


>
>
>
>
>
>
|

|



>
>
>
>
>
>
|













>













|







>
|
>
>
>
>







>








|










|










>







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
	}
    }
    dict set realopts key $cookiename
    dict set realopts value $cookieval
    {*}$http(-cookiejar) storeCookie $realopts
}

# http::GetTextLine --
#
#	Get one line with the stream in crlf mode.
#	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} {
    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 [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 [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
    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 $coding2]
	}
	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 $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)]} {
	    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 {
		    $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 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)]} {
	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
#
# 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
#		  premature EOF.
#
# Side Effects
#	Clean up the socket

proc http::Eot {token {reason {}}} {
    variable $token







|







4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
#
# 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 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
	# The response is complete.
	set state(status) ok
    }

    if {[string length $state(body)] > 0} {
	if {[catch {
	    foreach coding [ContentEncoding $token] {












		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"} {



		set state(body) [encoding convertfrom $enc $state(body)]

	    }

	    # Translate text line endings.
	    set state(body) [string map {\r\n \n \r \n} $state(body)]
	}


    }

    Finish $token $reason

}



















































































# http::wait --
#
#	See documentation for details.
#
# Arguments:
#	token	Connection token.







>
>
>
>
>
>
>
>
>
>
>
>
|
>















>
>
>
|
>





>
>
|
>

>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	# 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)]
		}
	    }
	} 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)]
		}
	    }

	    # 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.
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
            -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]
	if {$sep eq "="} {
	    set sep &
	} else {
	    set sep =
	}
    }
    return $result
}

# http::mapReply --
#
#	Do x-www-urlencoded character mapping
#
# Arguments:
#	string	The string the needs to be encoded
#
# Results:
#       The encoded string

proc http::mapReply {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 {$http(-urlencoding) ne ""} {

	set string [encoding convertto $http(-urlencoding) $string]
	return [string map $formMap $string]
    }
    set converted [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(-proxyport)] ||
	    ![string length $http(-proxyport)]
	} {
	    set http(-proxyport) 8080
	}





	return [list $http(-proxyhost) $http(-proxyport)]
    }


}

# 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]} {
	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"
	    }



	}
    } 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"
    }
}





# Return the list of content-encoding transformations we need to do in order.






















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 }
		gzip - x-gzip { lappend r gunzip }
		compress - x-compress { lappend r decompress }
		identity {}




		default {
		    return -code error "unsupported content-encoding \"$coding\""
		}
	    }
	}
    }
    return $r
}








|









|









|







>
|
>

<

|
<
<
<
<
<
|
<
<
<












|
<
>
>
|
|
|
|
|
>
>
>
>
>
|
|
>
>
















|











>
>
>













>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|

<

>
>
>
>

|







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
            -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 [quoteString $i]
	if {$sep eq "="} {
	    set sep &
	} else {
	    set sep =
	}
    }
    return $result
}

# http::quoteString --
#
#	Do x-www-urlencoded character mapping
#
# Arguments:
#	string	The string the needs to be encoded
#
# Results:
#       The encoded 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-]} {
	set string [encoding convertto -profile replace $http(-urlencoding) $string]
    } else {
	set string [encoding convertto $http(-urlencoding) $string]

    }
    return [string map $formMap $string]





}




# 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)]) || ($http(-proxyhost) eq {})} {

        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[-_]?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 deflateX }
		gzip - x-gzip { lappend r gunzip }

		identity {}
		br {
		    return -code error\
			    "content-encoding \"br\" not implemented"
		}
		default {
		    Log "unknown content-encoding \"$coding\" ignored"
		}
	    }
	}
    }
    return $r
}

3611
3612
3613
3614
3615
3616
3617














































3618
3619
3620























































































































































































































































































































































































































































































































































3621
3622
3623
3624
3625
	    # channel might have been closed in the callback
	    catch {chan event $chan readable {}}
	    return
	}
    }
}















































proc http::make-transformation-chunked {chan command} {
    coroutine [namespace current]::dechunk$chan ::http::ReceiveChunked $chan $command
    chan event $chan readable [namespace current]::dechunk$chan























































































































































































































































































































































































































































































































































}

# Local variables:
# indent-tabs-mode: t
# End:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





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
	    # 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::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
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}}}]

|
1
2
if {![package vsatisfies [package provide Tcl] 8.6-]} {return}
package ifneeded http 2.10b2 [list tclPkgSetup $dir http 2.10b2 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister ::http::mapReply}}}]

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
# 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
#
# 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

# 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.





|
|
|
|
|







<
<
<
<
|







1
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 © 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.
#





package require -exact tcl 9.0b2

# 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
#
# (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)








    } 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
	    }







|
>
>
>
>
>
>
>
>




>







39
40
41
42
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 [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
		{::tcl::MacOSXPkgUnknown ::tclPkgUnknown}}
    } else {
	package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
    }

    # Set up the 'clock' ensemble

    namespace eval ::tcl::clock [list variable TclLibDir $::tcl_library]

    proc ::tcl::initClock {} {
	# Auto-loading stubs for 'clock.tcl'

	foreach cmd {add format scan} {
	    proc ::tcl::clock::$cmd args {
		variable TclLibDir
		source [file join $TclLibDir clock.tcl]
		return [uplevel 1 [info level 0]]
	    }
	}



	rename ::tcl::initClock {}

    }
    ::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
# differently, specially when stderr is not available)

if {[namespace which -command tclLog] eq ""} {
    proc tclLog {string} {
	catch {puts stderr $string}
    }
}







<
|
<
<
|
|
|
<
<
<
|
<
|
>
>
|
>

<












|







105
106
107
108
109
110
111

112


113
114
115



116

117
118
119
120
121
122

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
		{::tcl::MacOSXPkgUnknown ::tclPkgUnknown}}
    } else {
	package unknown {::tcl::tm::UnknownHandler ::tclPkgUnknown}
    }

    # Set up the 'clock' ensemble


    proc clock args {


	set cmdmap [dict create]
	foreach cmd {add clicks format microseconds milliseconds scan seconds} {
	    dict set cmdmap $cmd ::tcl::clock::$cmd



	}

	namespace inscope ::tcl::clock [list namespace ensemble create -command \
	    [uplevel 1 [list ::namespace origin [::lindex [info level 0] 0]]] \
	    -map $cmdmap]
	::tcl::unsupported::clock::configure -init-complete
	uplevel 1 [info level 0]
    }

}

# 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 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
		# 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} {
		    set cinfo [string range $cinfo 0 150]
		    while {[string bytelength $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"







|

|







210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
		# 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 length [encoding convertto utf-8 $cinfo]] > 150} {
		    set cinfo [string range $cinfo 0 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
	    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]
	if {$name eq "::"} {
	    set name ""
	}
	if {$ret != 0} {
	    dict append opts -errorinfo \
		    "\n    (expanding command prefix \"$name\" in unknown)"
	    return -options $opts $msg
	}
	# 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







|






|







299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
	    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 [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 $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
# 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


    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 {[info exists auto_index($name)]} {
	    namespace eval :: $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
	    }
	}

    }

    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
	    }


	}
    }
    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.







>






|
>
>
|
>

|











>
|
>



<



<
<
<
<
<
|
>
>
|
<







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
# 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
    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 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
    }






    # 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
	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
		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)} {







|







439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
	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 -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)} {
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568

    auto_load_index

    foreach pattern $patternList {
        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)
            }
        }
    }
}

# auto_execok --
#







|







555
556
557
558
559
560
561
562
563
564
565
566
567
568
569

    auto_load_index

    foreach pattern $patternList {
        foreach name [array names auto_index $pattern] {
            if {([namespace which -command $name] eq "")
		    && ([namespace qualifiers $pattern] eq [namespace qualifiers $name])} {
                namespace inscope :: $auto_index($name)
            }
        }
    }
}

# auto_execok --
#
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
    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 \
	    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]
    }







|







588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
    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 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
	    if {[file exists $file] && ![file isdirectory $file]} {
		return [set auto_execs($name) [list $file]]
	    }
	}
	return ""
    }

    set path "[file dirname [info nameof]];.;"
    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;"







|







618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
	    if {[file exists $file] && ![file isdirectory $file]} {
		return [set auto_execs($name) [list $file]]
	    }
	}
	return ""
    }

    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
	    # 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"
	} 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"
		}
	    }
	}
    } else {
	if {[string first $nsrc $ndest] >= 0} {
	    set srclen [expr {[llength [file split $nsrc]] - 1}]
	    set ndest [lindex [file split $ndest] $srclen]







|











|







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
	    # 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 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 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
      ###
      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
      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]







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
      ###
      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 \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]
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
        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
      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
      }
    }
    return $buffer
  }
  set fin [open $pkgidxfile r]
  fconfigure $fin -encoding utf-8 -eofchar \032
  set dat [read $fin]
  close $fin
  set trace 0
  #if {[file tail $path] eq "tool"} {
  #  set trace 1
  #}
  set thisline {}







|



















|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
        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 \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
      }
    }
    return $buffer
  }
  set fin [open $pkgidxfile r]
  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 {}
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
	    } else {
        file attributes [file join $d2 $ftail] -readonly 1
	    }
    }
  }

  if {$::tcl_platform(platform) eq {unix}} {
    file attributes $d2 -permissions 0755
  } else {
    file attributes $d2 -readonly 1
  }
}

proc ::practcl::copyDir {d1 d2 {toplevel 1}} {
  #if {$toplevel} {







|







|







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 0o644
	    } else {
        file attributes [file join $d2 $ftail] -readonly 1
	    }
    }
  }

  if {$::tcl_platform(platform) eq {unix}} {
    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
###
# 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}
    1 msgcat          1.7.1  {msgcat msgcat.tcl}
    1 opt             0.4.8  {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::shell 1.1.4  {platform shell.tcl}
    1 tcltest         2.5.3  {tcltest tcltest.tcl}
  } {
    if {$isafe && !$safe} continue
    package ifneeded $package $version  [list source [file join $dir {*}$file]]
  }
}} $dir




<


|

|


|

|





1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
###
# Package manifest for all Tcl packages included in the /library file system
###
apply {{dir} {

  set isafe [interp issafe]
  foreach {safe package version file} {
    0 http            2.10b2 {http http.tcl}
    1 msgcat          1.7.1  {msgcat msgcat.tcl}
    1 opt             0.4.9  {opt optparse.tcl}
    0 cookiejar       0.2.0  {cookiejar cookiejar.tcl}
    0 tcl::idna       1.0.1  {cookiejar idna.tcl}
    0 platform        1.0.19 {platform platform.tcl}
    0 platform::shell 1.1.4  {platform shell.tcl}
    1 tcltest         2.5.8  {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
# 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.
#
# 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,






|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 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 © 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,
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    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.
    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.







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    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 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
# 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







>







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
#	    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
#	    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.







|







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 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.
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
# 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 {






	# Check self namespace to determine environment
	switch -exact -- [namespace which self] {
	    {::oo::define::self} {
		# We are within a class definition
		return [namespace qualifiers [self]]
	    }
	    {::oo::Helpers::self} {
		# We are within an object
		set Class [info object class [self]]
		# Check for classless defined object
		if {$Class eq {::oo::object}} {
		    return [namespace qualifiers [self]]
		}
		# Class defined object
		return [namespace qualifiers $Class]
	    }
	    default {
		# Not in object environment
		return [namespace current]
	    }
	}
    }
}

# Initialize the default locale
proc msgcat::mcutil::getsystemlocale {} {
    global env







|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<







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
# 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 {} {
    set ns [uplevel 2 { namespace current }]

    if {![string match {::oo::*} $ns]} {
	# Not in object environment
	return $ns
    }

    # Check self namespace to determine environment
    switch -exact -- [uplevel 2 { namespace which -command self }] {
	{::oo::define::self} {
	    # We are within a class definition
	    return [namespace qualifiers [uplevel 2 { self }]]
	}
	{::oo::Helpers::self} {
	    # We are within an object
	    set Class [info object class [uplevel 2 { self }]]
	    # Check for classless defined object
	    if {$Class eq {::oo::object}} {
		return [namespace qualifiers [uplevel 2 { self }]]
	    }
	    # Class defined object
	    return [namespace qualifiers $Class]
	}
	default {
	    # Not in object environment
	    return $ns

	}
    }
}

# Initialize the default locale
proc msgcat::mcutil::getsystemlocale {} {
    global env

Changes to library/msgcat/pkgIndex.tcl.

1
2
if {![package vsatisfies [package provide Tcl] 8.7-]} {return}
package ifneeded msgcat 1.7.1 [list source [file join $dir msgcat.tcl]]

|
1
2
if {![package vsatisfies [package provide Tcl] 8.7-]} {return}
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
# 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

namespace eval ::tcl {

    # Exported APIs
    namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \
             OptProc OptProcArgGiven OptParse \
	     Lempty Lget \













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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.9

namespace eval ::tcl {

    # Exported APIs
    namespace export OptKeyRegister OptKeyDelete OptKeyError OptKeyParse \
             OptProc OptProcArgGiven OptParse \
	     Lempty Lget \
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    # 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 ;-)
#
# 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







|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    # 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 ;-)
#
# 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

# 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
# is complex and there is maybe some places where the
# string rep might be calculated at great exense. 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







|

|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

# 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 structure
# is complex and there is maybe some places where the
# 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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
        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,
# 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]







|







222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
        variable OptDesc
        if {![info exists OptDesc($descKey)]} {
            return -code error "Unknown option description key \"$descKey\""
        }
        set OptDesc($descKey)
    }

# 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]
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
	set item [lindex $descriptions $adress]
	if {[OptIsPrg $item]} {
	    return [OptCurAddr $item $start]
	} else {
	    return $start
	}
    }
    # 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)
	lappend adress 2
	Lvarset descriptions $adress [list 1 $value]
	#                                  ^hasBeenSet flag
    }

    # empty state means done/paste the end of the program
    proc OptState {item} {
        lindex $item 0
    }

    # current state
    proc OptCurState {descriptions} {
        OptState [OptCurDesc $descriptions]
    }

    #######
    # Arguments manipulation

    # Returns the argument that has to be processed now
    proc OptCurrentArg {lst} {
        lindex $lst 0
    }
    # Advance to next argument
    proc OptNextArg {argsName} {
        uplevel 1 [list Lvarpop1 $argsName]
    }
    #######










|


|

|





|












|



|







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
	set item [lindex $descriptions $adress]
	if {[OptIsPrg $item]} {
	    return [OptCurAddr $item $start]
	} else {
	    return $start
	}
    }
    # Set the value field of the current instruction.
    proc OptCurSetValue {descriptionsName value} {
	upvar $descriptionsName descriptions
	# 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.
    proc OptState {item} {
        lindex $item 0
    }

    # current state
    proc OptCurState {descriptions} {
        OptState [OptCurDesc $descriptions]
    }

    #######
    # Arguments manipulation

    # Returns the argument that has to be processed now.
    proc OptCurrentArg {lst} {
        lindex $lst 0
    }
    # Advance to next argument.
    proc OptNextArg {argsName} {
        uplevel 1 [list Lvarpop1 $argsName]
    }
    #######



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
		    # no flags at all was given with expr
		    # {![string match "*-*" $Args]}
		    lappend vnamesLst [OptName $item]
		    set var [OptValue $item]
		} else {
		    set var [OptDefaultValue $item]
		}







|







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 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]
		}
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
	    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"
            }
	    return $arg
        }
	any {
	    return $arg
	}







|







597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
	    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 {$arg ni $typeArgs} {
                error "invalid choice"
            }
	    return $arg
        }
	any {
	    return $arg
	}

Changes to library/opt/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded opt 0.4.8 [list source [file join $dir optparse.tcl]]











|
1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded 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
# 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.
#
# 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 {}






|
|







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 © 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 {}

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 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,
#			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







|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# 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 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

    try {
	set fileList [glob -directory $dir -tails -types {r f} -- \
		{*}$patternList]
    } on error {msg opt} {
	return -options $opt $msg
    }



    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"} {







>
>
>







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
		    }
		}
	    }
	    proc tclPkgUnknown args {}
	    package unknown tclPkgUnknown

	    # Stub out the unknown command so package can call into each other
	    # during their initialilzation.

	    proc unknown {args} {}

	    # Stub out the auto_import mechanism

	    proc auto_import {args} {}








|







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 initialization.

	    proc unknown {args} {}

	    # Stub out the auto_import mechanism

	    proc auto_import {args} {}

729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
	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.
    set cmdline "package ifneeded $opts(-name) $opts(-version) "

    set cmdList {}
    set lazyFileList {}

    # Handle -load and -source specs
    foreach key {load source} {







|







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 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
# 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.
#
# 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



|
|







1
2
3
4
5
6
7
8
9
10
11
12
# parray:
# Print the contents of a global array on stdout.
#
# 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
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]]

|
|

1
2
3
package ifneeded platform        1.0.19 [list source -encoding utf-8 [file join $dir platform.tcl]]
package ifneeded platform::shell 1.1.4 [list source -encoding utf-8 [file join $dir shell.tcl]]

Changes to library/platform/platform.tcl.

25
26
27
28
29
30
31

32
33

34
35
36
37
38
39
40
# 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

# % arm*   -> arm
# % sun4*  -> sparc

# % intel  -> ix86
# % i*86*  -> ix86
# % Power* -> powerpc
# % x86_64 + wordSize 4 => x86 code
#
# OS specific
# % AIX are always powerpc machines







>


>







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
    set cpu  $tcl_platform(machine)

    switch -glob -- $cpu {
	sun4* {
	    set cpu sparc
	}
	intel -

	i*86* {
	    set cpu ix86
	}
	x86_64 {
	    if {$tcl_platform(wordSize) == 4} {
		# See Example <1> at the top of this file.
		set cpu ix86
	    }
	}

	"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"} {







>









>














<
<
<







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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 {



	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
		    append cpu 64
		}
	    }
	}
	osf1 {
	    set plat tru64
	}



    }

    return "${plat}-${cpu}"
}

# -- platform::identify
#







>
>
>







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
	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} {




		incr major -4
		append plat 10.$major
		return "${plat}-${cpu}"
	    }

	}
	linux {
	    # Look for the libc*.so and determine its version
	    # (libc5/6, libc6 further glibc 2.X)

	    set v unknown








|
>
>
>
>




>







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 > 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
    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
    # 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







|







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 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
	macosx-x86_64 {
	    lappend res macosx-i386-x86_64
	}
	macosx-ix86 {
	    lappend res macosx-universal macosx-i386-x86_64
	}
	macosx*-*    {
	    # 10.5+
	    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 }









		    default { set alt {} }
		}

		if {$v ne ""} {
		    foreach {major minor} [split $v .] break

		    # Add 10.5 to 10.minor to patterns.
		    set res {}


































		    for {set j $minor} {$j >= 5} {incr j -1} {

			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}







|







|
>
>
>
>
>
>
>
>
>






<

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>







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+,11.0+
	    if {[regexp {macosx([^-]*)-(.*)} $id -> v cpu]} {

		switch -exact -- $cpu {
		    ix86    {
			lappend alt i386-x86_64
			lappend alt universal
		    }
		    x86_64  {
			if {[lindex [split $::tcl_platform(osVersion) .] 0] < 19} {
			    set alt i386-x86_64
			} else {
			    set alt {}
			}
		    }
		    arm  {
			lappend alt x86_64
		    }
		    default { set alt {} }
		}

		if {$v ne ""} {
		    foreach {major minor} [split $v .] break


		    set res {}
		    if {$major eq 13} {
			# Add 13.0 to 13.minor to patterns.
			for {set j $minor} {$j >= 0} {incr j -1} {
			    lappend res macosx${major}.${j}-${cpu}
			    foreach a $alt {
				lappend res macosx${major}.${j}-$a
			    }
			}
			set major 12
			set minor 5
		    }
		    if {$major eq 12} {
			# Add 12.0 to 12.minor to patterns.
			for {set j $minor} {$j >= 0} {incr j -1} {
			    lappend res macosx${major}.${j}-${cpu}
			    foreach a $alt {
				lappend res macosx${major}.${j}-$a
			    }
			}
			set major 11
			set minor 5
		    }
		    if {$major eq 11} {
			# Add 11.0 to 11.minor to patterns.
			for {set j $minor} {$j >= 0} {incr j -1} {
			    lappend res macosx${major}.${j}-${cpu}
			    foreach a $alt {
				lappend res macosx${major}.${j}-$a
			    }
			}
			set major 10
			set minor 15
		    }
		    # Add 10.5 to 10.minor to patterns.
		    for {set j $minor} {$j >= 5} {incr j -1} {
			if {$cpu ne "arm"} {
			    lappend res macosx${major}.${j}-${cpu}
			}
			foreach a $alt {
			    lappend res macosx${major}.${j}-$a
			}
		    }

		    # Add unversioned patterns for 10.3/10.4 builds.
		    lappend res macosx-${cpu}
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
    return $res
}


# ### ### ### ######### ######### #########
## Ready

package provide platform 1.0.14

# ### ### ### ######### ######### #########
## Demo application

if {[info exists argv0] && ($argv0 eq [info script])} {
    puts ====================================
    parray tcl_platform







|







427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
    return $res
}


# ### ### ### ######### ######### #########
## Ready

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
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
    # conflict with this one.
    lappend code {package forget platform}
    # Inject our platform package
    lappend code [list source $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
    # conflict with this one.
    lappend code {package forget platform}
    # Inject our platform package
    lappend code [list source $base]
    # Query and print the architecture
    lappend code {puts [platform::identify]}
    # And done
    lappend code {exit 0}

    set arch [RUN $shell [join $code \n]]








|



|




















|



|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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 preexisting platform package, it might be in
    # conflict with this one.
    lappend code {package forget platform}
    # Inject our platform package
    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 preexisting platform package, it might be in
    # conflict with this one.
    lappend code {package forget platform}
    # Inject our platform package
    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
    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
    # 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
    # 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"} {







|






|







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, 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
    # 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"} {

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
# 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.
#
# 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

# Create the safe namespace
namespace eval ::safe {
    # Exported API:
    namespace export interpCreate interpInit interpConfigure interpDelete \
	interpAddToAccessPath interpFindInAccessPath setLogCmd
}









|












|







1
2
3
4
5
6
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 © 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.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
#
#  API entry points that needs argument parsing :
#
####

# Interface/entry point function and front end for "Create"
proc ::safe::interpCreate {args} {




    set Args [::tcl::OptKeyParse ::safe::interpCreate $args]
    RejectExcessColons $child


    InterpCreate $child $accessPath \
	[InterpStatics] [InterpNested] $deleteHook
}

proc ::safe::interpInit {args} {




    set Args [::tcl::OptKeyParse ::safe::interpIC $args]
    if {![::interp exists $child]} {
	return -code error "\"$child\" is not an interpreter"
    }
    RejectExcessColons $child


    InterpInit $child $accessPath \
	[InterpStatics] [InterpNested] $deleteHook
}

# 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 \







>
>
>
>


>
>

|



>
>
>
>





>
>

|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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 $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 $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

# 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} {

    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 \
		[list -accessPath $state(access_path)] \
		[list -statics    $state(staticsok)]   \
		[list -nested     $state(nestedok)]    \
	        [list -deleteHook $state(cleanupHook)]]]





	}
	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







>










|



|
>
>
>
>
>







125
126
127
128
129
130
131
132
133
134
135
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

	    set TMP [list \
		[list -accessPath $state(access_path)] \
		[list -statics    $state(staticsok)]   \
		[list -nested     $state(nestedok)]    \
	        [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
	    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)]







		}
		-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:
		    return -code error\
			"ambigous query (get or set -noStatics ?)\
				use -statics instead"
		}
		-nestedLoadOk {
		    return -code error\
			"ambigous query (get or set -nestedLoadOk ?)\







>
>
>
>
>
>
>














|







169
170
171
172
173
174
175
176
177
178
179
180
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 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
	    # not been given:
	    if {![::tcl::OptProcArgGiven -accessPath]} {
		set doreset 0
		set accessPath $state(access_path)
	    } else {
		set doreset 1
	    }






	    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)
	    if {$doreset} {
		if {[catch {::interp eval $child {auto_reset}} msg]} {
		    Log $child "auto_reset failed: $msg"
		} else {
		    Log $child "successful auto_reset" NOTICE
		}








>
>
>
>
>
>



















|
>
|
>
|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
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)
	    }
	    # 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
# {},...  {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.

# + 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)
#                      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


		       } {
    # 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
}

#
# InterpSetConfig (was setAccessPath) :
#    Sets up child virtual auto_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} {
    global auto_path


    # 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)







|
>


|









>
>













|




|





|
>
>
>
>
|

>







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 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)
#                      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 $autoPath $withAutoPath
}

#
# InterpSetConfig (was setAccessPath) :
#    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.
#
#    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
	    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
	}



	# Add 1st level sub dirs (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]






    }

    Log $child "Setting accessPath=($access_path) staticsok=$staticsok\
		nestedok=$nestedok deletehook=($deletehook)" 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 morepaths [::tcl::tm::list]
    set firstpass 1
    while {[llength $morepaths]} {
	set addpaths $morepaths
	set morepaths {}

	foreach dir $addpaths {







>
>
|



>
>
>
>
>
>




>
>
>









<
















>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    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 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 {
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 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





    SyncAccessPath $child
    return
}

#
#





















# FindInAccessPath:
#    Search for a real directory and returns its virtual Id (including the
#    "$")


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







>
>
>
>





|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


>
>










>







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
}

#
#
# 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
# into a preexisting safe interpreter.
proc ::safe::InterpInit {
			 child
			 access_path
			 staticsok
			 nestedok
			 deletehook


		     } {
    # Configure will generate an access_path when access_path is empty.
    InterpSetConfig $child $access_path $staticsok $nestedok $deletehook

    # 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







>
>


|







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 $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
    ::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)"







<
<







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



    # 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)"
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
    foreach sub [interp children $child] {
        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
    # 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







|







689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
    foreach sub [interp children $child] {
        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
    # 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
	::interp delete $child
	Log $child "Deleted" NOTICE
    }

    return
}

# Set (or get) the logging mecanism

proc ::safe::setLogCmd {args} {
    variable Log
    set la [llength $args]
    if {$la == 0} {
	return $Log
    } elseif {$la == 1} {







|







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 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
	}
    }
}

# ------------------- 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.
#
proc ::safe::SyncAccessPath {child} {

    namespace upvar ::safe [VarName $child] state

    set child_access_path $state(access_path,child)

    ::interp eval $child [list set auto_path $child_access_path]

    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
    # ensures this condition.

    ::interp eval $child [list \
	      set tcl_library [lindex $child_access_path 0]]

}

# 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







|
|


>



>
|

|
|
|
>

|




>







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 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]

	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 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
}

# 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} {

    Log $child "GLOB ! $args" NOTICE
    set cmd {}
    set at 0
    array set got {
	-directory 0
	-nocomplain 0
	-join 0







<
<
<






>







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} {



    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
		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'"

	    }
	    default {
		break
	    }
	}
	if {$got(--)} break
    }







>







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
	# 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.
    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.








|







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 (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
    # 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
	set contents [read $f]
	close $f
	::interp eval $child [list info script $file]
    } msg opt]
    if {$code == 0} {
	set code [catch {::interp eval $child $contents} msg opt]
	set replacementMsg $msg







|







1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
    # 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 \x1A
	set contents [read $f]
	close $f
	::interp eval $child [list info script $file]
    } msg opt]
    if {$code == 0} {
	set code [catch {::interp eval $child $contents} msg opt]
	set replacementMsg $msg
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
    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]

    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)"
	    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"
	    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)"
	}
    } else {
	# file loading

	# get the real path from the virtual one.
	try {
	    set file [TranslatePath $child $file]







|
|











|






|
|
|




|
|
|







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
    set argc [llength $args]
    if {$argc > 2} {
	set msg "load error: too many arguments"
	Log $child "$msg ($argc) {$file $args}"
	return -code error $msg
    }

    # 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 $prefix to $target)"
	    return -code error "permission denied (nested load)"
	}
    }

    # Determine what kind of load is requested
    if {$file eq ""} {
	# 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 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
	} on error msg {
	    Log $child $msg
	    return -code error "permission denied (path)"
	}
    }

    try {
	return [::interp invokehidden $child load $file $package $target]
    } on error msg {
	# Some packages return no error message.
	set msg0 "load of binary library for package $package failed"
	if {$msg eq {}} {
	    set msg $msg0
	} else {
	    set msg "$msg0: $msg"
	}
	Log $child $msg
	return -code error $msg







|

|
|







1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
	} on error msg {
	    Log $child $msg
	    return -code error "permission denied (path)"
	}
    }

    try {
	return [::interp invokehidden $child load $file $prefix $target]
    } on error msg {
	# 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
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217
1218
1219





1220
1221
1222
1223
1224
1225
1226

proc ::safe::Setup {} {
    ####
    #
    # Setup the arguments parsing
    #
    ####


    # Share the descriptions
    set temp [::tcl::OptKeyRegister {
	{-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"}
    }]






    # 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







>


|






<
>
>
>
>
>







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

proc ::safe::Setup {} {
    ####
    #
    # Setup the arguments parsing
    #
    ####
    variable AutoPathSync

    # Share the descriptions
    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
    setLogCmd {}

    # Log eventually.
    # To enable error logging, set Log to {puts stderr} for instance,
    # via setLogCmd.
    return
}













































namespace eval ::safe {
    # internal variables





















    # 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 )

    # 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










}

::safe::Setup








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















>




>
>
>
>
>
>
>
>
>
>



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
    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 (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
# 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(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(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(::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::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::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(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(::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::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]]

<



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>






>








>











>





|
>
>
>
|
|
>
>
>
>
>
>
>
>
>





|
<
<
<
<
<
<
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111






# Tcl autoload index file, version 2.0

# 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::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::tmpath) [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(writeFile) [list ::tcl::Pkg::source [file join $dir writefile.tcl]]






Changes to library/tcltest/pkgIndex.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded tcltest 2.5.3 [list source [file join $dir tcltest.tcl]]











|
1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded tcltest 2.5.8 [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
# 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
# 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

    # Compatibility support for dumb variables defined in tcltest 1
    # Do not use these.  Call [package provide Tcl] and [info patchlevel]
    # yourself.  You don't need tcltest to wrap it for you.
    variable version [package provide Tcl]
    variable patchLevel [info patchlevel]




##### 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)

    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]












|
|
|



<





|


|

|


>
>
>











>
|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
28
29
30
31
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 © 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.


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.8

    # Compatibility support for dumb variables defined in tcltest 1
    # Do not use these.  Call [package require] and [info patchlevel]
    # yourself.  You don't need tcltest to wrap it for you.
    variable version [package require Tcl 8.5-]
    variable patchLevel [info patchlevel]

    # 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 {!$fullutf} {
	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
	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
    # 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!
	    unset $varName
	}
	array set $varName $value
    }

    # save the original environment so that it can be restored later
    ArrayDefault originalEnv [array get ::env]







|









|







151
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 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]} {
	    # 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

    # 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
    # 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]







|







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 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
    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.
    #
    # Note that $filesExisted lists only those files that exist in
    # the original [temporaryDirectory].
    Default filesMade {} AcceptList
    Default filesExisted {} AcceptList
    proc FillFilesExisted {} {
	variable filesExisted







|







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
    # 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
    # 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
    # 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]} {







|







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 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

    variable ChannelsWeOpened; array set ChannelsWeOpened {}
    # output goes to stdout by default
    Default outputChannel stdout
    proc outputChannel { {filename ""} } {
	variable outputChannel
	variable ChannelsWeOpened


	# 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
	# 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
	# 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,







>









|




|







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] 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 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
	switch -exact -- $filename {
	    stderr -
	    stdout {
		set outputChannel $filename
	    }
	    default {
		set outputChannel [open $filename a]



		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]]]







>
>
>







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
    }

    # errors go to stderr by default
    Default errorChannel stderr
    proc errorChannel { {filename ""} } {
	variable errorChannel
	variable ChannelsWeOpened


	# 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]



		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]]]







>



















>
>
>







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
    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.
    # 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







|







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 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
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
	    }
	}
	return $valid
    }

    proc IsVerbose {level} {
	variable Option
	return [expr {[lsearch -exact $Option(-verbose) $level] >= 0}]
    }

    # 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







|







648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
	    }
	}
	return $valid
    }

    proc IsVerbose {level} {
	variable Option
	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
	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 $directory
    }

    # Directory where files should be created
    Option -tmpdir [workingDirectory] {
	Save temporary files in the specified directory.







|







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 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
    proc AcceptLoadFile { file } {
	if {$file eq {}} {return $file}
	set file [file join [temporaryDirectory] $file]
	return [AcceptReadable $file]
    }
    proc ReadLoadScript {args} {
	variable Option


	if {$Option(-loadfile) eq {}} {return}
	set tmp [open $Option(-loadfile) r]



	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]







>
>


>
>
>







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
}

#####################################################################

# tcltest::Debug* --
#
#     Internal helper procedures to write out debug information
#     dependent on the chosen level. A test shell may overide
#     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.







|







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 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
    if {$n2 eq {}} {return}
    if {![info exists testConstraints($n2)]} {
	if {[catch {testConstraint $n2 [eval [ConstraintInitializer $n2]]}]} {
	    testConstraint $n2 0
	}
    }
}
































# 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.
#







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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}

    # By default, tests that expose known bugs are skipped.

    ConstraintInitializer knownBug {format 0}

    # By default, non-portable tests are skipped.

    ConstraintInitializer nonPortable {format 0}





    # Some tests require user interaction.

    ConstraintInitializer userInteraction {format 0}

    # Some tests must be skipped if the interpreter is not in
    # interactive mode

    ConstraintInitializer interactive \
	    {expr {[info exists ::tcl_interactive] && $::tcl_interactive}}








|



|



|
>
>
>
>



|







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 {expr 0}

    # By default, tests that expose known bugs are skipped.

    ConstraintInitializer knownBug {expr 0}

    # By default, non-portable tests are skipped.

    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 {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
    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 {close $f}
	    set code
    }

    # Set asyncPipeClose constraint: 1 means this platform supports
    # async flush and async close on a pipe.
    #







|







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 {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.
    #
1322
1323
1324
1325
1326
1327
1328


1329
1330



1331
1332
1333
1334
1335
1336
1337
	    }
	    removeFile $file
        }
	set code
    }

    ConstraintInitializer stdio {


	set code 0
	if {![catch {set f [open "|[list [interpreter]]" w]}]} {



	    if {![catch {puts $f exit}]} {
		if {![catch {close $f}]} {
		    set code 1
		}
	    }
	}
	set code







>
>


>
>
>







1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
	    }
	    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
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
#

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.
    # 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 ""








|







1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
#

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-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 ""

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
#   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
#			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.
#
# 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


    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
    # 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








|


















>
>












|







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 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.
#
# 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

    # 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

2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
	    }
	}
    }

    if {[IsVerbose msec] || [IsVerbose usec]} {
	set t [expr {[clock microseconds] - $timeStart}]
	if {[IsVerbose usec]} {
	    puts [outputChannel] "++++ $name took $t μs"
	}
	if {[IsVerbose msec]} {
	    puts [outputChannel] "++++ $name took [expr {round($t/1000.)}] ms"
	}
    }

    # if skipped, it is safe to return here







|







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 \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
		[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]



		set testLine [expr {[lsearch -regexp \
			[split [read $testFd] "\n"] \
			"^\[ \t\]*test [string map {. \\.} $name] "] + 1}]
		close $testFd
	    }
	}
	if {[info exists testLine]} {







>
>
>







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
	    puts [outputChannel] "---- errorCode(setup): $errorCodeRes(setup)"
	}
    }
    if {$processTest && $scriptFailure} {
	if {$scriptCompare} {
	    puts [outputChannel] "---- Error testing result: $scriptMatch"
	} else {

	    puts [outputChannel] "---- Result was:\n$actualAnswer"



	    puts [outputChannel] "---- Result should have been\
		    ($match matching):\n$result"
	}
    }
    if {$errorCodeFailure} {
	puts [outputChannel] "---- Error code was: '$errorCodeRes(body)'"
	puts [outputChannel] "---- Error code should have been: '$errorCode'"
    }
    if {$codeFailure} {







>
|
>
>
>

|







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[Asciify $actualAnswer]"
	    } errMsg]} {
		puts [outputChannel] "\n---- Result was:\n<error printing result: $errMsg>"
	    }
	    puts [outputChannel] "---- Result should have been\
		    ($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
	    return 1
	}
    } else {
	# "constraints" argument exists;
	# make sure that the constraints are satisfied.

	set doTest 0

	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







>







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
    }

    # 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
    # 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}







|







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 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
	}

	# 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]} {
	    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







|







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 {[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

proc tcltest::runAllTests { {shell ""} } {
    variable testSingleFile
    variable numTestFiles
    variable numTests
    variable failFiles
    variable DefaultValue


    FillFilesExisted
    if {[llength [info level 0]] == 1} {
	set shell [interpreter]
    }

    set testSingleFile false







>







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
	set tail [file tail $file]
	puts [outputChannel] $tail
	flush [outputChannel]

	if {[singleProcess]} {
	    if {[catch {
		incr numTestFiles
		uplevel 1 [list ::source $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} {







|







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 -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
		}
		lappend childargv $opt $value
	    }
	    set cmd [linsert $childargv 0 | $shell $file]
	    if {[catch {
		incr numTestFiles
		set pipeFd [open $cmd "r"]



		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]+)}







>
>
>







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

    # 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]]

	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]}]







|







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 -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
#	absolute path to the file created
#
# Side effects:
#	None.

proc tcltest::makeFile {contents name {directory ""}} {
    variable filesMade


    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



    if {[string index $contents end] eq "\n"} {
	puts -nonewline $fd $contents
    } else {
	puts $fd $contents
    }
    close $fd








>
>












|
>
>
>







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]
    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
# Results:
#	content of the named file
#
# Side effects:
#	None.

proc tcltest::viewFile {name {directory ""}} {


    FillFilesExisted
    if {[llength [info level 0]] == 2} {
	set directory [temporaryDirectory]
    }
    set fullName [file join $directory $name]
    set f [open $fullName]



    set data [read -nonewline $f]
    close $f
    return $data
}

# tcltest::bytestring --
#







>
>






>
>
>







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
#    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.
#



# Arguments:
#	string being converted
#
# Results:
#	result fom encoding
#
# Side effects:
#	None


proc tcltest::bytestring {string} {
    return [encoding convertfrom identity $string]

}

# tcltest::OpenFiles --
#
#	used in io tests, uses testchannel
#
# Arguments:







>
>
>









>
|
|
>







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 {!$::tcltest::fullutf} {
    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
	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
    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
    # 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 {







|








|







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 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 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
#   [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.
#
#   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
#      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.







|


|







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 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 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
#	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
#	The subcommands 'add' and 'remove' manipulate the list of paths to
#	search for Tcl Modules. The subcommand 'list' has no sideeffects.

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.
    #
    # 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







|

|








|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#	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'.
#
# Side effects
#	The subcommands 'add' and 'remove' manipulate the list of paths to
#	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 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
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.
#
#	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
#	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.








|








|







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 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.
#
# 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
#
# Arguments
#	None
#
# Results
#	None.
#
# Sideeffects
#	May add paths to the list of defaults.

proc ::tcl::tm::Defaults {} {
    global env tcl_platform

    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] \







|





|







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
#
# Arguments
#	None
#
# Results
#	None.
#
# 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
    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] \
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
    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

	    }
	}
    }
    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
#	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
    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
	}







>
>
|
>
















|



|







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
    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] {
                # 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.
#
# 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
    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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Africa/Accra) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Africa/Abidjan)

















































Changes to library/tzdata/Africa/Cairo.

125
126
127
128
129
130
131


























































































































































132
    {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}


























































































































































}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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.

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    {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}
}







|















|















|















|















|















|















|















|









|





|





62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    {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}
    {1682215200 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}
    {1927159200 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}
    {2172103200 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}
    {2417047200 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}
    {2661991200 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}
    {2906935200 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}
    {3151879200 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}
    {3396823200 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}
    {3549837600 3600 0 +01}
    {3577658400 0 1 +01}
    {3580682400 3600 0 +01}
    {3607898400 0 1 +01}
    {3611527200 3600 0 +01}
    {3638743200 0 1 +01}
    {3641767200 3600 0 +01}
    {3669588000 0 1 +01}
    {3672612000 3600 0 +01}
    {3699828000 0 1 +01}
    {3703456800 3600 0 +01}
}

Changes to library/tzdata/Africa/El_Aaiun.

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    {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}
}







|















|















|















|















|















|















|















|









|





|





51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    {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}
    {1682215200 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}
    {1927159200 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}
    {2172103200 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}
    {2417047200 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}
    {2661991200 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}
    {2906935200 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}
    {3151879200 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}
    {3396823200 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}
    {3549837600 3600 0 +01}
    {3577658400 0 1 +01}
    {3580682400 3600 0 +01}
    {3607898400 0 1 +01}
    {3611527200 3600 0 +01}
    {3638743200 0 1 +01}
    {3641767200 3600 0 +01}
    {3669588000 0 1 +01}
    {3672612000 3600 0 +01}
    {3699828000 0 1 +01}
    {3703456800 3600 0 +01}
}

Changes to library/tzdata/Africa/Juba.

32
33
34
35
36
37
38

39
    {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}

}







>

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Lagos) {
    {-9223372036854775808 816 0 LMT}



    {-1588464816 3600 0 WAT}
}



|
>
>
>
|

1
2
3
4
5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Lagos) {
    {-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/Nairobi.

1
2
3
4

5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:Africa/Nairobi) {
    {-9223372036854775808 8836 0 LMT}

    {-1309746436 10800 0 EAT}
    {-1262314800 9000 0 +0230}
    {-946780200 9900 0 +0245}
    {-315629100 10800 0 EAT}
}




>
|
|
|
|

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}
    {-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
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Anguilla) $TZData(:America/Port_of_Spain)

|
|

|
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/Anguilla) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Antigua.

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
}
set TZData(:America/Antigua) $TZData(:America/Port_of_Spain)

|
|

|
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/Antigua) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Aruba.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Curacao)]} {
    LoadTimeZoneFile America/Curacao
}
set TZData(:America/Aruba) $TZData(:America/Curacao)

|
|

|
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/Aruba) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Atikokan.

1


2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Atikokan) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
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) $TZData(:America/Panama)









Changes to library/tzdata/America/Bahia_Banderas.

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/Bahia_Banderas) {
    {-9223372036854775808 -25260 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}







|







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/Bahia_Banderas) {
    {-9223372036854775808 -25260 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    {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}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

61
62
63
64
65
66
67


























































































































































68
    {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}


























































































































































}

Changes to library/tzdata/America/Barbados.

1
2
3
4
5

6






7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Barbados) {
    {-9223372036854775808 -14309 0 LMT}
    {-1451678491 -14309 0 BMT}

    {-1199217691 -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}




|
>
|
>
>
>
>
>
>







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}
    {-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/Belize.

47
48
49
50
51
52
53







































54
55




56
57
58
59
60
    {-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}







































    {-859744800 -19800 1 -0530}
    {-848255400 -21600 0 CST}




    {123919200 -18000 1 CDT}
    {129618000 -21600 0 CST}
    {409039200 -18000 1 CDT}
    {413874000 -21600 0 CST}
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>





47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
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}
    {-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
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Blanc-Sablon) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
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) $TZData(:America/Puerto_Rico)









Changes to library/tzdata/America/Bogota.

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}
}







|

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}
    {729057600 -18000 0 -05}
}

Changes to library/tzdata/America/Cambridge_Bay.

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/Cambridge_Bay) {
    {-9223372036854775808 0 0 -00}
    {-1577923200 -25200 0 MST}
    {-880210800 -21600 1 MWT}
    {-769395600 -21600 1 MPT}
    {-765388800 -25200 0 MST}




    {-147891600 -18000 1 MDDT}








    {-131562000 -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}








>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>







1
2
3
4
5
6
7
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}
    {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/Chihuahua.

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}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-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}







|







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}
    {-1234807200 -25200 0 MST}
    {-1220292000 -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
    {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}
    {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}
}







<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

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}



    {1667120400 -21600 0 CST}























































































































































}

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}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -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
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Atikokan)]} {
    LoadTimeZoneFile America/Atikokan
}
set TZData(:America/Coral_Harbour) $TZData(:America/Atikokan)

|
|

|
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/Coral_Harbour) $TZData(:America/Panama)

Changes to library/tzdata/America/Creston.

1


2
3
4
5
6
7
8
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Creston) {
    {-9223372036854775808 -27964 0 LMT}
    {-2713882436 -25200 0 MST}
    {-1680454800 -28800 0 PST}
    {-1627833600 -25200 0 MST}
}

>
>
|
|
<
<
<
<
<
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) $TZData(:America/Phoenix)





Changes to library/tzdata/America/Curacao.

1


2
3
4
5
6
7
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Curacao) {
    {-9223372036854775808 -16547 0 LMT}
    {-1826738653 -16200 0 -0430}
    {-157750200 -14400 0 AST}
}

>
>
|
|
<
<
<
<
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) $TZData(:America/Puerto_Rico)




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
# 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}

    {-147884400 -25200 1 YDDT}
    {-131554800 -32400 0 YST}

    {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}












>


>







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
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Dominica) $TZData(:America/Port_of_Spain)

|
|

|
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/Dominica) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Grand_Turk.

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    {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}
    {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}







|
<







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 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
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Grenada) $TZData(:America/Port_of_Spain)

|
|

|
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/Grenada) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Guadeloupe.

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
}
set TZData(:America/Guadeloupe) $TZData(:America/Port_of_Spain)

|
|

|
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/Guadeloupe) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Guyana.

1
2
3
4

5
6
7
8
# 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}
}



|
>
|
|
|

1
2
3
4
5
6
7
8
9
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Guyana) {
    {-9223372036854775808 -13959 0 LMT}
    {-1843589241 -14400 0 -04}
    {-1730577600 -13500 0 -0345}
    {176096700 -10800 0 -03}
    {701841600 -14400 0 -04}
}

Changes to library/tzdata/America/Hermosillo.

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/Hermosillo) {
    {-9223372036854775808 -26632 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}







|







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/Hermosillo) {
    {-9223372036854775808 -26632 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}

Changes to library/tzdata/America/Inuvik.

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/Inuvik) {
    {-9223372036854775808 0 0 -00}
    {-536457600 -28800 0 PST}
    {-147888000 -21600 1 PDDT}




    {-131558400 -28800 0 PST}










    {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}





|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>







1
2
3
4
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}
    {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
# 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}


    {-147898800 -10800 1 EDDT}








    {-131569200 -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}







>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>







1
2
3
4
5
6
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}
    {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
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Curacao)]} {
    LoadTimeZoneFile America/Curacao
}
set TZData(:America/Kralendijk) $TZData(:America/Curacao)

|
|

|
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/Kralendijk) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Lower_Princes.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Curacao)]} {
    LoadTimeZoneFile America/Curacao
}
set TZData(:America/Lower_Princes) $TZData(:America/Curacao)

|
|

|
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/Lower_Princes) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Marigot.

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
}
set TZData(:America/Marigot) $TZData(:America/Port_of_Spain)

|
|

|
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/Marigot) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Matamoros.

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}
    {-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}



|







1
2
3
4
5
6
7
8
9
10
11
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Matamoros) {
    {-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
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Mazatlan) {
    {-9223372036854775808 -25540 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}







|







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/Mazatlan) {
    {-9223372036854775808 -25540 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1343066400 -21600 0 CST}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 1 MDT}
    {-1207159200 -25200 0 MST}
    {-1191344400 -21600 0 CST}
    {-873828000 -25200 0 MST}
    {-661539600 -28800 0 PST}
    {28800 -25200 0 MST}
    {828867600 -21600 1 MDT}
    {846403200 -25200 0 MST}
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
    {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}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

61
62
63
64
65
66
67


























































































































































68
    {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}


























































































































































}

Changes to library/tzdata/America/Merida.

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    {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}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

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}


























































































































































}

Changes to library/tzdata/America/Mexico_City.

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}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-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}







|







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}
    {-1234807200 -25200 0 MST}
    {-1220292000 -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
    {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}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

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}


























































































































































}

Changes to library/tzdata/America/Miquelon.

1
2
3
4
5
6
7
8
9
10
11
12
# 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}




|







1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Miquelon) {
    {-9223372036854775808 -13480 0 LMT}
    {-1847650520 -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}

Changes to library/tzdata/America/Monterrey.

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    {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}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

57
58
59
60
61
62
63


























































































































































64
    {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}


























































































































































}

Changes to library/tzdata/America/Montserrat.

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
}
set TZData(:America/Montserrat) $TZData(:America/Port_of_Spain)

|
|

|
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/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
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Nassau) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:America/Toronto)




















































































































































































































































































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
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Nipigon) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:America/Toronto)





































































































































































































































































Changes to library/tzdata/America/Nuuk.

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    {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}
}







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    {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 0 -02}
    {1698541200 -7200 0 -02}
    {1711846800 -3600 1 -01}
    {1729990800 -7200 0 -02}
    {1743296400 -3600 1 -01}
    {1761440400 -7200 0 -02}
    {1774746000 -3600 1 -01}
    {1792890000 -7200 0 -02}
    {1806195600 -3600 1 -01}
    {1824944400 -7200 0 -02}
    {1837645200 -3600 1 -01}
    {1856394000 -7200 0 -02}
    {1869094800 -3600 1 -01}
    {1887843600 -7200 0 -02}
    {1901149200 -3600 1 -01}
    {1919293200 -7200 0 -02}
    {1932598800 -3600 1 -01}
    {1950742800 -7200 0 -02}
    {1964048400 -3600 1 -01}
    {1982797200 -7200 0 -02}
    {1995498000 -3600 1 -01}
    {2014246800 -7200 0 -02}
    {2026947600 -3600 1 -01}
    {2045696400 -7200 0 -02}
    {2058397200 -3600 1 -01}
    {2077146000 -7200 0 -02}
    {2090451600 -3600 1 -01}
    {2108595600 -7200 0 -02}
    {2121901200 -3600 1 -01}
    {2140045200 -7200 0 -02}
    {2153350800 -3600 1 -01}
    {2172099600 -7200 0 -02}
    {2184800400 -3600 1 -01}
    {2203549200 -7200 0 -02}
    {2216250000 -3600 1 -01}
    {2234998800 -7200 0 -02}
    {2248304400 -3600 1 -01}
    {2266448400 -7200 0 -02}
    {2279754000 -3600 1 -01}
    {2297898000 -7200 0 -02}
    {2311203600 -3600 1 -01}
    {2329347600 -7200 0 -02}
    {2342653200 -3600 1 -01}
    {2361402000 -7200 0 -02}
    {2374102800 -3600 1 -01}
    {2392851600 -7200 0 -02}
    {2405552400 -3600 1 -01}
    {2424301200 -7200 0 -02}
    {2437606800 -3600 1 -01}
    {2455750800 -7200 0 -02}
    {2469056400 -3600 1 -01}
    {2487200400 -7200 0 -02}
    {2500506000 -3600 1 -01}
    {2519254800 -7200 0 -02}
    {2531955600 -3600 1 -01}
    {2550704400 -7200 0 -02}
    {2563405200 -3600 1 -01}
    {2582154000 -7200 0 -02}
    {2595459600 -3600 1 -01}
    {2613603600 -7200 0 -02}
    {2626909200 -3600 1 -01}
    {2645053200 -7200 0 -02}
    {2658358800 -3600 1 -01}
    {2676502800 -7200 0 -02}
    {2689808400 -3600 1 -01}
    {2708557200 -7200 0 -02}
    {2721258000 -3600 1 -01}
    {2740006800 -7200 0 -02}
    {2752707600 -3600 1 -01}
    {2771456400 -7200 0 -02}
    {2784762000 -3600 1 -01}
    {2802906000 -7200 0 -02}
    {2816211600 -3600 1 -01}
    {2834355600 -7200 0 -02}
    {2847661200 -3600 1 -01}
    {2866410000 -7200 0 -02}
    {2879110800 -3600 1 -01}
    {2897859600 -7200 0 -02}
    {2910560400 -3600 1 -01}
    {2929309200 -7200 0 -02}
    {2942010000 -3600 1 -01}
    {2960758800 -7200 0 -02}
    {2974064400 -3600 1 -01}
    {2992208400 -7200 0 -02}
    {3005514000 -3600 1 -01}
    {3023658000 -7200 0 -02}
    {3036963600 -3600 1 -01}
    {3055712400 -7200 0 -02}
    {3068413200 -3600 1 -01}
    {3087162000 -7200 0 -02}
    {3099862800 -3600 1 -01}
    {3118611600 -7200 0 -02}
    {3131917200 -3600 1 -01}
    {3150061200 -7200 0 -02}
    {3163366800 -3600 1 -01}
    {3181510800 -7200 0 -02}
    {3194816400 -3600 1 -01}
    {3212960400 -7200 0 -02}
    {3226266000 -3600 1 -01}
    {3245014800 -7200 0 -02}
    {3257715600 -3600 1 -01}
    {3276464400 -7200 0 -02}
    {3289165200 -3600 1 -01}
    {3307914000 -7200 0 -02}
    {3321219600 -3600 1 -01}
    {3339363600 -7200 0 -02}
    {3352669200 -3600 1 -01}
    {3370813200 -7200 0 -02}
    {3384118800 -3600 1 -01}
    {3402867600 -7200 0 -02}
    {3415568400 -3600 1 -01}
    {3434317200 -7200 0 -02}
    {3447018000 -3600 1 -01}
    {3465766800 -7200 0 -02}
    {3479072400 -3600 1 -01}
    {3497216400 -7200 0 -02}
    {3510522000 -3600 1 -01}
    {3528666000 -7200 0 -02}
    {3541971600 -3600 1 -01}
    {3560115600 -7200 0 -02}
    {3573421200 -3600 1 -01}
    {3592170000 -7200 0 -02}
    {3604870800 -3600 1 -01}
    {3623619600 -7200 0 -02}
    {3636320400 -3600 1 -01}
    {3655069200 -7200 0 -02}
    {3668374800 -3600 1 -01}
    {3686518800 -7200 0 -02}
    {3699824400 -3600 1 -01}
    {3717968400 -7200 0 -02}
    {3731274000 -3600 1 -01}
    {3750022800 -7200 0 -02}
    {3762723600 -3600 1 -01}
    {3781472400 -7200 0 -02}
    {3794173200 -3600 1 -01}
    {3812922000 -7200 0 -02}
    {3825622800 -3600 1 -01}
    {3844371600 -7200 0 -02}
    {3857677200 -3600 1 -01}
    {3875821200 -7200 0 -02}
    {3889126800 -3600 1 -01}
    {3907270800 -7200 0 -02}
    {3920576400 -3600 1 -01}
    {3939325200 -7200 0 -02}
    {3952026000 -3600 1 -01}
    {3970774800 -7200 0 -02}
    {3983475600 -3600 1 -01}
    {4002224400 -7200 0 -02}
    {4015530000 -3600 1 -01}
    {4033674000 -7200 0 -02}
    {4046979600 -3600 1 -01}
    {4065123600 -7200 0 -02}
    {4078429200 -3600 1 -01}
    {4096573200 -7200 0 -02}
}

Changes to library/tzdata/America/Ojinaga.

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}
    {-1234807200 -25200 0 MST}
    {-1220292000 -21600 0 CST}
    {-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}







|







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}
    {-1234807200 -25200 0 MST}
    {-1220292000 -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
    {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}
}







|
|
>
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
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}
    {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}

    {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/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
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Pangnirtung) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:America/Iqaluit)

























































































































































































































































Changes to library/tzdata/America/Port_of_Spain.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Port_of_Spain) {
    {-9223372036854775808 -14764 0 LMT}
    {-1825098836 -14400 0 AST}
}

>
>
|
|
<
<
<
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) $TZData(:America/Puerto_Rico)



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
# 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}




|
|
|
|
|
|













>







1
2
3
4
5
6
7
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/Punta_Arenas) {
    {-9223372036854775808 -17020 0 LMT}
    {-2524504580 -16965 0 SMT}
    {-1892661435 -18000 0 -05}
    {-1688410800 -16965 0 SMT}
    {-1619205435 -14400 0 -04}
    {-1593806400 -16965 0 SMT}
    {-1335986235 -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}
    {-736632000 -14400 1 -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}

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
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Rainy_River) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:America/Winnipeg)





































































































































































































































































Changes to library/tzdata/America/Rankin_Inlet.

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/Rankin_Inlet) {
    {-9223372036854775808 0 0 -00}
    {-410227200 -21600 0 CST}
    {-147895200 -14400 1 CDDT}


    {-131565600 -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}





|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
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}
    {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/Resolute.

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/Resolute) {
    {-9223372036854775808 0 0 -00}
    {-704937600 -21600 0 CST}
    {-147895200 -14400 1 CDDT}


    {-131565600 -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}





|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
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}
    {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/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
# 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}



|
|
|
|
|
|
|














|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Santiago) {
    {-9223372036854775808 -16965 0 LMT}
    {-2524504635 -16965 0 SMT}
    {-1892661435 -18000 0 -05}
    {-1688410800 -16965 0 SMT}
    {-1619205435 -14400 0 -04}
    {-1593806400 -16965 0 SMT}
    {-1335986235 -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}
    {-736635600 -14400 1 -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}
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    {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}







|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    {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}
    {1662868800 -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}

Changes to library/tzdata/America/Scoresbysund.

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    {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}
}







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
    {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 -3600 0 -01}
    {1729990800 -7200 0 -02}
    {1743296400 -3600 1 -01}
    {1761440400 -7200 0 -02}
    {1774746000 -3600 1 -01}
    {1792890000 -7200 0 -02}
    {1806195600 -3600 1 -01}
    {1824944400 -7200 0 -02}
    {1837645200 -3600 1 -01}
    {1856394000 -7200 0 -02}
    {1869094800 -3600 1 -01}
    {1887843600 -7200 0 -02}
    {1901149200 -3600 1 -01}
    {1919293200 -7200 0 -02}
    {1932598800 -3600 1 -01}
    {1950742800 -7200 0 -02}
    {1964048400 -3600 1 -01}
    {1982797200 -7200 0 -02}
    {1995498000 -3600 1 -01}
    {2014246800 -7200 0 -02}
    {2026947600 -3600 1 -01}
    {2045696400 -7200 0 -02}
    {2058397200 -3600 1 -01}
    {2077146000 -7200 0 -02}
    {2090451600 -3600 1 -01}
    {2108595600 -7200 0 -02}
    {2121901200 -3600 1 -01}
    {2140045200 -7200 0 -02}
    {2153350800 -3600 1 -01}
    {2172099600 -7200 0 -02}
    {2184800400 -3600 1 -01}
    {2203549200 -7200 0 -02}
    {2216250000 -3600 1 -01}
    {2234998800 -7200 0 -02}
    {2248304400 -3600 1 -01}
    {2266448400 -7200 0 -02}
    {2279754000 -3600 1 -01}
    {2297898000 -7200 0 -02}
    {2311203600 -3600 1 -01}
    {2329347600 -7200 0 -02}
    {2342653200 -3600 1 -01}
    {2361402000 -7200 0 -02}
    {2374102800 -3600 1 -01}
    {2392851600 -7200 0 -02}
    {2405552400 -3600 1 -01}
    {2424301200 -7200 0 -02}
    {2437606800 -3600 1 -01}
    {2455750800 -7200 0 -02}
    {2469056400 -3600 1 -01}
    {2487200400 -7200 0 -02}
    {2500506000 -3600 1 -01}
    {2519254800 -7200 0 -02}
    {2531955600 -3600 1 -01}
    {2550704400 -7200 0 -02}
    {2563405200 -3600 1 -01}
    {2582154000 -7200 0 -02}
    {2595459600 -3600 1 -01}
    {2613603600 -7200 0 -02}
    {2626909200 -3600 1 -01}
    {2645053200 -7200 0 -02}
    {2658358800 -3600 1 -01}
    {2676502800 -7200 0 -02}
    {2689808400 -3600 1 -01}
    {2708557200 -7200 0 -02}
    {2721258000 -3600 1 -01}
    {2740006800 -7200 0 -02}
    {2752707600 -3600 1 -01}
    {2771456400 -7200 0 -02}
    {2784762000 -3600 1 -01}
    {2802906000 -7200 0 -02}
    {2816211600 -3600 1 -01}
    {2834355600 -7200 0 -02}
    {2847661200 -3600 1 -01}
    {2866410000 -7200 0 -02}
    {2879110800 -3600 1 -01}
    {2897859600 -7200 0 -02}
    {2910560400 -3600 1 -01}
    {2929309200 -7200 0 -02}
    {2942010000 -3600 1 -01}
    {2960758800 -7200 0 -02}
    {2974064400 -3600 1 -01}
    {2992208400 -7200 0 -02}
    {3005514000 -3600 1 -01}
    {3023658000 -7200 0 -02}
    {3036963600 -3600 1 -01}
    {3055712400 -7200 0 -02}
    {3068413200 -3600 1 -01}
    {3087162000 -7200 0 -02}
    {3099862800 -3600 1 -01}
    {3118611600 -7200 0 -02}
    {3131917200 -3600 1 -01}
    {3150061200 -7200 0 -02}
    {3163366800 -3600 1 -01}
    {3181510800 -7200 0 -02}
    {3194816400 -3600 1 -01}
    {3212960400 -7200 0 -02}
    {3226266000 -3600 1 -01}
    {3245014800 -7200 0 -02}
    {3257715600 -3600 1 -01}
    {3276464400 -7200 0 -02}
    {3289165200 -3600 1 -01}
    {3307914000 -7200 0 -02}
    {3321219600 -3600 1 -01}
    {3339363600 -7200 0 -02}
    {3352669200 -3600 1 -01}
    {3370813200 -7200 0 -02}
    {3384118800 -3600 1 -01}
    {3402867600 -7200 0 -02}
    {3415568400 -3600 1 -01}
    {3434317200 -7200 0 -02}
    {3447018000 -3600 1 -01}
    {3465766800 -7200 0 -02}
    {3479072400 -3600 1 -01}
    {3497216400 -7200 0 -02}
    {3510522000 -3600 1 -01}
    {3528666000 -7200 0 -02}
    {3541971600 -3600 1 -01}
    {3560115600 -7200 0 -02}
    {3573421200 -3600 1 -01}
    {3592170000 -7200 0 -02}
    {3604870800 -3600 1 -01}
    {3623619600 -7200 0 -02}
    {3636320400 -3600 1 -01}
    {3655069200 -7200 0 -02}
    {3668374800 -3600 1 -01}
    {3686518800 -7200 0 -02}
    {3699824400 -3600 1 -01}
    {3717968400 -7200 0 -02}
    {3731274000 -3600 1 -01}
    {3750022800 -7200 0 -02}
    {3762723600 -3600 1 -01}
    {3781472400 -7200 0 -02}
    {3794173200 -3600 1 -01}
    {3812922000 -7200 0 -02}
    {3825622800 -3600 1 -01}
    {3844371600 -7200 0 -02}
    {3857677200 -3600 1 -01}
    {3875821200 -7200 0 -02}
    {3889126800 -3600 1 -01}
    {3907270800 -7200 0 -02}
    {3920576400 -3600 1 -01}
    {3939325200 -7200 0 -02}
    {3952026000 -3600 1 -01}
    {3970774800 -7200 0 -02}
    {3983475600 -3600 1 -01}
    {4002224400 -7200 0 -02}
    {4015530000 -3600 1 -01}
    {4033674000 -7200 0 -02}
    {4046979600 -3600 1 -01}
    {4065123600 -7200 0 -02}
    {4078429200 -3600 1 -01}
    {4096573200 -7200 0 -02}
}

Changes to library/tzdata/America/St_Barthelemy.

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
}
set TZData(:America/St_Barthelemy) $TZData(:America/Port_of_Spain)

|
|

|
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/St_Barthelemy) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/St_Kitts.

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
}
set TZData(:America/St_Kitts) $TZData(:America/Port_of_Spain)

|
|

|
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/St_Kitts) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/St_Lucia.

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
}
set TZData(:America/St_Lucia) $TZData(:America/Port_of_Spain)

|
|

|
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/St_Lucia) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/St_Thomas.

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
}
set TZData(:America/St_Thomas) $TZData(:America/Port_of_Spain)

|
|

|
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/St_Thomas) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/St_Vincent.

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
}
set TZData(:America/St_Vincent) $TZData(:America/Port_of_Spain)

|
|

|
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/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
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Thunder_Bay) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:America/Toronto)













































































































































































































































































Changes to library/tzdata/America/Tijuana.

1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Tijuana) {
    {-9223372036854775808 -28084 0 LMT}
    {-1514736000 -25200 0 MST}
    {-1451667600 -28800 0 PST}
    {-1343062800 -25200 0 MST}
    {-1234803600 -28800 0 PST}
    {-1222963200 -25200 1 PDT}
    {-1207242000 -28800 0 PST}
    {-873820800 -25200 1 PWT}
    {-769395600 -25200 1 PPT}




|







1
2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:America/Tijuana) {
    {-9223372036854775808 -28084 0 LMT}
    {-1514739600 -25200 0 MST}
    {-1451667600 -28800 0 PST}
    {-1343062800 -25200 0 MST}
    {-1234803600 -28800 0 PST}
    {-1222963200 -25200 1 PDT}
    {-1207242000 -28800 0 PST}
    {-873820800 -25200 1 PWT}
    {-769395600 -25200 1 PPT}

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
    {-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}
    {-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}







|
|
|
|
|
|







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}
    {-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
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(America/Port_of_Spain)]} {
    LoadTimeZoneFile America/Port_of_Spain
}
set TZData(:America/Tortola) $TZData(:America/Port_of_Spain)

|
|

|
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/Tortola) $TZData(:America/Puerto_Rico)

Changes to library/tzdata/America/Virgin.

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
}
set TZData(:America/Virgin) $TZData(:America/Port_of_Spain)

|
|

|
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/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
# 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}

    {-147884400 -25200 1 YDDT}
    {-131554800 -32400 0 YST}

    {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}












>


>







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
# created by tools/tclZIC.tcl - do not edit



set TZData(:America/Yellowknife) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:America/Edmonton)

























































































































































































































































Changes to library/tzdata/Antarctica/Casey.

10
11
12
13
14
15
16





17
    {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}





}







>
>
>
>
>

10
11
12
13
14
15
16
17
18
19
20
21
22
    {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}
    {1615640400 28800 0 +08}
    {1633190460 39600 0 +11}
    {1647090000 28800 0 +08}
    {1664640060 39600 0 +11}
    {1678291200 28800 0 +08}
}

Changes to library/tzdata/Antarctica/DumontDUrville.

1


2
3
4
5
6
7
8
# created by tools/tclZIC.tcl - do not edit



set TZData(:Antarctica/DumontDUrville) {
    {-9223372036854775808 0 0 -00}
    {-725846400 36000 0 +10}
    {-566992800 0 0 -00}
    {-415497600 36000 0 +10}
}

>
>
|
|
<
<
<
<
<
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) $TZData(:Pacific/Port_Moresby)





Changes to library/tzdata/Antarctica/Macquarie.

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}
    {-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}







|







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}
    {-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/Syowa.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Antarctica/Syowa) {
    {-9223372036854775808 0 0 -00}
    {-407808000 10800 0 +03}
}

>
>
|
|
<
<
<
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) $TZData(:Asia/Riyadh)



Changes to library/tzdata/Antarctica/Vostok.

1
2
3
4
5



6
# created by tools/tclZIC.tcl - do not edit

set TZData(:Antarctica/Vostok) {
    {-9223372036854775808 0 0 -00}
    {-380073600 21600 0 +06}



}




|
>
>
>

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 25200 0 +07}
    {760035600 0 0 -00}
    {783648000 25200 0 +07}
    {1702839600 18000 0 +05}
}

Changes to library/tzdata/Arctic/Longyearbyen.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Oslo)]} {
    LoadTimeZoneFile Europe/Oslo
}
set TZData(:Arctic/Longyearbyen) $TZData(:Europe/Oslo)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin
}
set TZData(:Arctic/Longyearbyen) $TZData(:Europe/Berlin)

Changes to library/tzdata/Asia/Almaty.

50
51
52
53
54
55
56

57
    {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}

}







>

50
51
52
53
54
55
56
57
58
    {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}
    {1709229600 18000 0 +05}
}

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
    {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}
    {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}
}







|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

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}
    {1645740000 10800 1 EEST}
    {1666908000 10800 0 +03}


























































































































































}

Changes to library/tzdata/Asia/Brunei.

1


2
3
4
5
6
7
# created by tools/tclZIC.tcl - do not edit



set TZData(:Asia/Brunei) {
    {-9223372036854775808 27580 0 LMT}
    {-1383464380 27000 0 +0730}
    {-1167636600 28800 0 +08}
}

>
>
|
|
<
<
<
<
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) $TZData(:Asia/Kuching)




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
    {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}
    {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}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

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}



























    {1666908000 10800 0 +03}































































































































}

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
# 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}
    {-844300800 10800 1 EEST}
    {-825822000 7200 0 EEST}
    {-812685600 10800 1 EEST}
    {-794199600 7200 0 EEST}
    {-779853600 10800 1 EEST}
    {-762656400 7200 0 EEST}
    {-748310400 10800 1 EEST}
    {-731127600 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}





|
>
>
|

|
|
|
|
|

|







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}
    {-933638400 10800 1 EEST}
    {-923097600 7200 0 EEST}
    {-919036800 10800 1 EEST}
    {-857347200 7200 0 EEST}
    {-844300800 10800 1 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}
    {-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
    {-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}
    {482277600 10800 1 IDT}
    {495579600 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}







|
|
|
|

|







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}
    {334101600 10800 1 IDT}
    {337730400 7200 0 IST}
    {452642400 10800 1 IDT}
    {462319200 7200 0 IST}
    {482277600 10800 1 IDT}
    {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
    {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}






}







|
>
>
|
|
|
|
|
|
|
|
>
>
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
>
>
|
|
|
|
|
>
>
|
|
|
>
>
|
|
>
>
|
|
|
|
|
|
>
>
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|
>
>
|
|
>
>
|
>
>
|
|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
>
>
|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>

120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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}
    {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
# 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}
    {-844300800 10800 1 EEST}
    {-825822000 7200 0 EEST}
    {-812685600 10800 1 EEST}
    {-794199600 7200 0 EEST}
    {-779853600 10800 1 EEST}
    {-762656400 7200 0 EEST}
    {-748310400 10800 1 EEST}
    {-731127600 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}





|
>
>
|

|
|
|
|
|

|







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}
    {-933638400 10800 1 EEST}
    {-923097600 7200 0 EEST}
    {-919036800 10800 1 EEST}
    {-857347200 7200 0 EEST}
    {-844300800 10800 1 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}
    {-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
    {-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}
    {482277600 10800 1 IDT}
    {495579600 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}







|
|
|
|

|







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}
    {334101600 10800 1 IDT}
    {337730400 7200 0 IST}
    {452642400 10800 1 IDT}
    {462319200 7200 0 IST}
    {482277600 10800 1 IDT}
    {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
    {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}






}







|
>
>
|
|
|
|
|
|
|
|
>
>
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
>
>
|
|
|
|
|
>
>
|
|
|
>
>
|
|
>
>
|
|
|
|
|
|
>
>
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
|
|
|
|
>
>
|
|
>
>
|
>
>
|
|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
>
>
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
|
>
>
|
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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}
    {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
# 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}
}



|
|





|



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 25590 0 LMT}
    {-2004073590 25590 0 PLMT}
    {-1851577590 25200 0 +07}
    {-852105600 28800 0 +08}
    {-782643600 32400 0 +09}
    {-767869200 25200 0 +07}
    {-718095600 28800 0 +08}
    {-457772400 25200 0 +07}
    {-315648000 28800 0 +08}
    {171820800 25200 0 +07}
}

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
# 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}
    {-844300800 10800 1 IDT}
    {-825822000 7200 0 IST}
    {-812685600 10800 1 IDT}
    {-794199600 7200 0 IST}
    {-779853600 10800 1 IDT}
    {-762656400 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}
    {-608947200 7200 0 IST}
    {-591847200 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}
    {-418262400 7200 0 IST}
    {-400032000 10800 1 IDT}
    {-387428400 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}
    {482277600 10800 1 IDT}
    {495579600 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}






|
>
>
|

|
|
|
|
|

|
|
|
|
|
|
|

|





|
|
|
|
|

|
|




|
|
|
|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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}
    {-933638400 10800 1 IDT}
    {-923097600 7200 0 IST}
    {-919036800 10800 1 IDT}
    {-857347200 7200 0 IST}
    {-844300800 10800 1 IDT}
    {-825811200 7200 0 IST}
    {-812678400 10800 1 IDT}
    {-794188800 7200 0 IST}
    {-779846400 10800 1 IDT}
    {-762652800 7200 0 IST}
    {-748310400 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}
    {-591840000 10800 1 IDT}
    {-572486400 7200 0 IST}
    {-558576000 10800 1 IDT}
    {-542851200 7200 0 IST}
    {-527731200 10800 1 IDT}
    {-514425600 7200 0 IST}
    {-490838400 10800 1 IDT}
    {-482976000 7200 0 IST}
    {-459388800 10800 1 IDT}
    {-451526400 7200 0 IST}
    {-428544000 10800 1 IDT}
    {-418262400 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}
    {334101600 10800 1 IDT}
    {337730400 7200 0 IST}
    {452642400 10800 1 IDT}
    {462319200 7200 0 IST}
    {482277600 10800 1 IDT}
    {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/Kuala_Lumpur.

1


2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit



set TZData(:Asia/Kuala_Lumpur) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Asia/Singapore)










Changes to library/tzdata/Asia/Qostanay.

51
52
53
54
55
56
57

58
    {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}

}







>

51
52
53
54
55
56
57
58
59
    {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}
    {1709229600 18000 0 +05}
}

Changes to library/tzdata/Asia/Singapore.

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}
    {-1167634800 26400 1 +0720}
    {-1073028000 26400 0 +0720}
    {-894180000 27000 0 +0730}
    {-879665400 32400 0 +09}
    {-767005200 27000 0 +0730}
    {378664200 28800 0 +08}
}











|

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}
    {-1167634800 26400 1 +0720}
    {-1073028000 26400 0 +0720}
    {-894180000 27000 0 +0730}
    {-879665400 32400 0 +09}
    {-767005200 27000 0 +0730}
    {378662400 28800 0 +08}
}

Changes to library/tzdata/Asia/Tehran.

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(: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}
    {283982400 12600 0 +0330}
    {290809800 16200 1 +0330}
    {306531000 12600 0 +0330}
    {322432200 16200 1 +0330}
    {338499000 12600 0 +0330}
    {673216200 16200 1 +0330}
    {685481400 12600 0 +0330}
    {701209800 16200 1 +0330}
    {717103800 12600 0 +0330}





|
>
|
|
|

|







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(:Asia/Tehran) {
    {-9223372036854775808 12344 0 LMT}
    {-1704165944 12344 0 TMT}
    {-1090466744 12600 0 +0330}
    {227820600 16200 1 +0330}
    {246227400 14400 0 +04}
    {259617600 18000 1 +04}
    {271108800 14400 0 +04}
    {283982400 12600 0 +0330}
    {296598600 16200 1 +0330}
    {306531000 12600 0 +0330}
    {322432200 16200 1 +0330}
    {338499000 12600 0 +0330}
    {673216200 16200 1 +0330}
    {685481400 12600 0 +0330}
    {701209800 16200 1 +0330}
    {717103800 12600 0 +0330}
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
    {1569094200 12600 0 +0330}
    {1584736200 16200 1 +0330}
    {1600630200 12600 0 +0330}
    {1616358600 16200 1 +0330}
    {1632252600 12600 0 +0330}
    {1647894600 16200 1 +0330}
    {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}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

69
70
71
72
73
74
75


























































































































































76
    {1569094200 12600 0 +0330}
    {1584736200 16200 1 +0330}
    {1600630200 12600 0 +0330}
    {1616358600 16200 1 +0330}
    {1632252600 12600 0 +0330}
    {1647894600 16200 1 +0330}
    {1663788600 12600 0 +0330}


























































































































































}

Changes to library/tzdata/Atlantic/Azores.

62
63
64
65
66
67
68


69
70
71
72
73
74
75
    {-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}







>
>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    {-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}
    {-623275200 -3600 1 -01}
    {-607550400 -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}

Changes to library/tzdata/Atlantic/Bermuda.

1
2
3
4





5






















6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit

set TZData(:Atlantic/Bermuda) {
    {-9223372036854775808 -15558 0 LMT}





    {-1262281242 -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}




>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 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/Jan_Mayen.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Oslo)]} {
    LoadTimeZoneFile Europe/Oslo
}
set TZData(:Atlantic/Jan_Mayen) $TZData(:Europe/Oslo)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Berlin)]} {
    LoadTimeZoneFile Europe/Berlin
}
set TZData(:Atlantic/Jan_Mayen) $TZData(:Europe/Berlin)

Changes to library/tzdata/Atlantic/Madeira.

62
63
64
65
66
67
68


69
70
71
72
73
74
75
    {-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}







>
>







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    {-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}
    {-623278800 0 1 +00}
    {-607554000 -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}

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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Atlantic/Reykjavik) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Africa/Abidjan)






































































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
# 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}
    {-883639800 37800 1 ACDT}
    {-876126600 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844677000 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813227400 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}






|
|

|

|

|







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}
    {-1672558200 37800 1 ACDT}
    {-1665387000 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876123000 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844673400 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-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
# 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}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 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}





|
|

|

|

|







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}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-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
# 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}
    {-883639800 37800 1 ACDT}
    {-876126600 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844677000 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813227400 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}







|
|

|

|

|







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}
    {-1672558200 37800 1 ACDT}
    {-1665387000 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876123000 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844673400 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Australia/Currie) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Australia/Hobart)














































































































































































































































































Changes to library/tzdata/Australia/Darwin.

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}
    {-883639800 37800 1 ACDT}
    {-876126600 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844677000 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-813227400 34200 0 ACST}
}






|
|

|

|

|

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}
    {-1672558200 37800 1 ACDT}
    {-1665387000 34200 0 ACST}
    {-883639800 37800 1 ACDT}
    {-876123000 34200 0 ACST}
    {-860398200 37800 1 ACDT}
    {-844673400 34200 0 ACST}
    {-828343800 37800 1 ACDT}
    {-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
# 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}
    {-883637100 35100 1 +0945}
    {-876123900 31500 0 +0945}
    {-860395500 35100 1 +0945}
    {-844674300 31500 0 +0945}
    {-836473500 35100 0 +0945}
    {152039700 35100 1 +0945}
    {162926100 31500 0 +0945}
    {436295700 35100 1 +0945}
    {447182100 31500 0 +0945}
    {690311700 35100 1 +0945}
    {699383700 31500 0 +0945}





|
|

|

|







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/Eucla) {
    {-9223372036854775808 30928 0 LMT}
    {-2337928528 31500 0 +0945}
    {-1672555500 35100 1 +0945}
    {-1665384300 31500 0 +0945}
    {-883637100 35100 1 +0945}
    {-876120300 31500 0 +0945}
    {-860395500 35100 1 +0945}
    {-844670700 31500 0 +0945}
    {-836473500 35100 0 +0945}
    {152039700 35100 1 +0945}
    {162926100 31500 0 +0945}
    {436295700 35100 1 +0945}
    {447182100 31500 0 +0945}
    {690311700 35100 1 +0945}
    {699383700 31500 0 +0945}

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
# created by tools/tclZIC.tcl - do not edit

set TZData(:Australia/Hobart) {
    {-9223372036854775808 35356 0 LMT}
    {-2345795356 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}
    {-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}






>
>
>
|
|
>

|

|

|







1
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}
    {-1615190400 39600 1 AEDT}
    {-1604304000 36000 0 AEST}
    {-1583920800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-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
# 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}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 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}





|
|

|

|

|







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}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-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/Melbourne.

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}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 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}





|
|

|

|

|







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}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-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
# 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}
    {-883634400 32400 1 AWDT}
    {-876121200 28800 0 AWST}
    {-860392800 32400 1 AWDT}
    {-844671600 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}





|
|

|

|







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}
    {-1672552800 32400 1 AWDT}
    {-1665381600 28800 0 AWST}
    {-883634400 32400 1 AWDT}
    {-876117600 28800 0 AWST}
    {-860392800 32400 1 AWDT}
    {-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
# 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}
    {-883641600 39600 1 AEDT}
    {-876128400 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844678800 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-813229200 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}





|
|

|

|

|







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}
    {-1672560000 39600 1 AEDT}
    {-1665388800 36000 0 AEST}
    {-883641600 39600 1 AEDT}
    {-876124800 36000 0 AEST}
    {-860400000 39600 1 AEDT}
    {-844675200 36000 0 AEST}
    {-828345600 39600 1 AEDT}
    {-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}

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/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

# created by tools/tclZIC.tcl - do not edit

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}
    {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}
}


|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>
1
2

























































































































































3

























































































































































4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Brussels)]} {

























































































































































    LoadTimeZoneFile Europe/Brussels

























































































































































}
set TZData(:Europe/Amsterdam) $TZData(:Europe/Brussels)

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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Copenhagen) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Europe/Berlin)





































































































































































































































































Changes to library/tzdata/Europe/Dublin.

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}
    {-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}



|
|







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 -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/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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Kiev) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Europe/Kyiv)
























































































































































































































































Changes to library/tzdata/Europe/Kirov.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    {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}
}







|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    {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 MSD}
    {606870000 14400 1 MSD}
    {622594800 10800 0 MSK}
    {638319600 14400 1 MSD}
    {654649200 10800 0 MSK}
    {670374000 14400 0 +04}
    {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.

66
67
68
69
70
71
72


73
74
75
76
77
78
79
    {-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}


    {-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}







>
>







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}

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

# created by tools/tclZIC.tcl - do not edit

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}
    {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}
}


|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>
1
2



























































































































































3


























































































































































4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Brussels)]} {



























































































































































    LoadTimeZoneFile Europe/Brussels


























































































































































}
set TZData(:Europe/Luxembourg) $TZData(:Europe/Brussels)

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

# created by tools/tclZIC.tcl - do not edit

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}
    {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}
}


|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>
1
2




























































































































































3



























































































































































4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Europe/Paris)]} {




























































































































































    LoadTimeZoneFile Europe/Paris



























































































































































}
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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Oslo) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Europe/Berlin)












































































































































































































































































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
    {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}
    {767743200 14400 0 MSD}
    {780436800 10800 0 MSK}
    {796165200 14400 1 MSD}
    {811886400 10800 0 MSK}
    {828219600 14400 1 MSD}
    {852066000 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}







|
|
|
|
|
|

|
|
|

|







27
28
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}
    {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}
    {780447600 10800 0 MSK}
    {796172400 14400 1 MSD}
    {811897200 10800 0 MSK}
    {828219600 14400 1 MSD}
    {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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Stockholm) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Europe/Berlin)























































































































































































































































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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Uzhgorod) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Europe/Kyiv)



























































































































































































































































Changes to library/tzdata/Europe/Volgograd.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
    {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}

}







|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

>

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    {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 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 +04}
    {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 +04}
    {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
# created by tools/tclZIC.tcl - do not edit



set TZData(:Europe/Zaporozhye) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
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) $TZData(:Europe/Kyiv)

























































































































































































































































Changes to library/tzdata/Iceland.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Atlantic/Reykjavik)]} {
    LoadTimeZoneFile Atlantic/Reykjavik
}
set TZData(:Iceland) $TZData(:Atlantic/Reykjavik)

|
|

|
1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Africa/Abidjan)]} {
    LoadTimeZoneFile Africa/Abidjan
}
set TZData(:Iceland) $TZData(:Africa/Abidjan)

Changes to library/tzdata/Indian/Christmas.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Christmas) {
    {-9223372036854775808 25372 0 LMT}
    {-2364102172 25200 0 +07}
}

>
>
|
|
<
<
<
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) $TZData(:Asia/Bangkok)



Changes to library/tzdata/Indian/Cocos.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Cocos) {
    {-9223372036854775808 23260 0 LMT}
    {-2209012060 23400 0 +0630}
}

>
>
|
|
<
<
<
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) $TZData(:Asia/Yangon)



Changes to library/tzdata/Indian/Kerguelen.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Kerguelen) {
    {-9223372036854775808 0 0 -00}
    {-631152000 18000 0 +05}
}

>
>
|
|
<
<
<
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) $TZData(:Indian/Maldives)



Changes to library/tzdata/Indian/Mahe.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Mahe) {
    {-9223372036854775808 13308 0 LMT}
    {-2006653308 14400 0 +04}
}

>
>
|
|
<
<
<
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) $TZData(:Asia/Dubai)



Changes to library/tzdata/Indian/Reunion.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Indian/Reunion) {
    {-9223372036854775808 13312 0 LMT}
    {-1848886912 14400 0 +04}
}

>
>
|
|
<
<
<
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) $TZData(:Asia/Dubai)



Changes to library/tzdata/Pacific/Apia.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    {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}
    {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}
    {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}
    {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}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

24
25
26
27
28
29
30





























































































































































31
    {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}





























































































































































}

Changes to library/tzdata/Pacific/Chuuk.

1


2
3
4
5
6
7
8
9
10
11
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Chuuk) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
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) $TZData(:Pacific/Port_Moresby)








Changes to library/tzdata/Pacific/Easter.

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
    {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}







|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
    {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}
    {1662868800 -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}

Changes to library/tzdata/Pacific/Efate.

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(: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}





>
>


|







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(:Pacific/Efate) {
    {-9223372036854775808 40396 0 LMT}
    {-1829387596 39600 0 +11}
    {125409600 43200 1 +11}
    {133876800 39600 0 +11}
    {433256400 43200 1 +11}
    {448977600 39600 0 +11}
    {464706000 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}

Changes to library/tzdata/Pacific/Enderbury.

1


2
3
4
5
6
7
8
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Enderbury) {
    {-9223372036854775808 -41060 0 LMT}
    {-2177411740 -43200 0 -12}
    {307627200 -39600 0 -11}
    {788871600 46800 0 +13}
}

>
>
|
|
<
<
<
<
<
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) $TZData(:Pacific/Kanton)





Changes to library/tzdata/Pacific/Fiji.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    {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}
    {2841573600 43200 0 +12}
    {2867580000 46800 1 +12}
    {2873023200 43200 0 +12}
    {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}
    {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}
    {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}
    {3404037600 46800 1 +12}
    {3409480800 43200 0 +12}
    {3435487200 46800 1 +12}
    {3440930400 43200 0 +12}
    {3466936800 46800 1 +12}
    {3472380000 43200 0 +12}
    {3498386400 46800 1 +12}
    {3503829600 43200 0 +12}
    {3529836000 46800 1 +12}
    {3535884000 43200 0 +12}
    {3561285600 46800 1 +12}
    {3567333600 43200 0 +12}
    {3593340000 46800 1 +12}
    {3598783200 43200 0 +12}
    {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}
    {3725186400 43200 0 +12}
    {3751192800 46800 1 +12}
    {3756636000 43200 0 +12}
    {3782642400 46800 1 +12}
    {3788085600 43200 0 +12}
    {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}
}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

27
28
29
30
31
32
33





























































































































































34
    {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}





























































































































































}

Changes to library/tzdata/Pacific/Funafuti.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Funafuti) {
    {-9223372036854775808 43012 0 LMT}
    {-2177495812 43200 0 +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/Funafuti) $TZData(:Pacific/Tarawa)



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 -12}
    {307627200 -39600 0 -11}
    {788871600 46800 0 +13}
}

Changes to library/tzdata/Pacific/Majuro.

1


2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Majuro) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
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) $TZData(:Pacific/Tarawa)









Changes to library/tzdata/Pacific/Niue.

1
2
3
4
5
6
7
8
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Niue) {
    {-9223372036854775808 -40780 0 LMT}
    {-2177412020 -40800 0 -1120}
    {-599575200 -41400 0 -1130}
    {276089400 -39600 0 -11}
}




|
<
|

1
2
3
4
5

6
7
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Niue) {
    {-9223372036854775808 -40780 0 LMT}
    {-543069620 -40800 0 -1120}

    {-173623200 -39600 0 -11}
}

Changes to library/tzdata/Pacific/Pohnpei.

1


2
3
4
5
6
7
8
9
10
11
12
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Pohnpei) {
    {-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}
}

>
>
|
|
<
<
<
<
<
<
<
<
<
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) $TZData(:Pacific/Guadalcanal)









Changes to library/tzdata/Pacific/Ponape.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Pohnpei)]} {
    LoadTimeZoneFile Pacific/Pohnpei
}
set TZData(:Pacific/Ponape) $TZData(:Pacific/Pohnpei)

|
|

|
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/Ponape) $TZData(:Pacific/Guadalcanal)

Changes to library/tzdata/Pacific/Rarotonga.

1
2
3
4

5
6
7
8
9
10
11
12
# 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}



|
>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Rarotonga) {
    {-9223372036854775808 48056 0 LMT}
    {-2209555256 -38344 0 LMT}
    {-543072056 -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}

Changes to library/tzdata/Pacific/Tongatapu.

1
2
3
4
5
6
7
8
9
10
11
12
13
# 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}



|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
# created by tools/tclZIC.tcl - do not edit

set TZData(:Pacific/Tongatapu) {
    {-9223372036854775808 44352 0 LMT}
    {-767189952 44400 0 +1220}
    {-284041200 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}

Changes to library/tzdata/Pacific/Truk.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Chuuk)]} {
    LoadTimeZoneFile Pacific/Chuuk
}
set TZData(:Pacific/Truk) $TZData(:Pacific/Chuuk)

|
|

|
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/Truk) $TZData(:Pacific/Port_Moresby)

Changes to library/tzdata/Pacific/Wake.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Wake) {
    {-9223372036854775808 39988 0 LMT}
    {-2177492788 43200 0 +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/Wake) $TZData(:Pacific/Tarawa)



Changes to library/tzdata/Pacific/Wallis.

1


2
3
4
5
6
# created by tools/tclZIC.tcl - do not edit



set TZData(:Pacific/Wallis) {
    {-9223372036854775808 44120 0 LMT}
    {-2177496920 43200 0 +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/Wallis) $TZData(:Pacific/Tarawa)



Changes to library/tzdata/Pacific/Yap.

1
2
3
4
5
# created by tools/tclZIC.tcl - do not edit
if {![info exists TZData(Pacific/Chuuk)]} {
    LoadTimeZoneFile Pacific/Chuuk
}
set TZData(:Pacific/Yap) $TZData(:Pacific/Chuuk)

|
|

|
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/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/word.tcl.

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.
#
# 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.






|
|







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 © 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
# Arguments:
# str -		String to search.
# start -	Index into string specifying starting point.

proc tcl_wordBreakAfter {str start} {
    variable ::tcl::WordBreakRE
    set result {-1 -1}



    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}

    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}



    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}



    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] \
		result word
    }
    return [lindex $word 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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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
    }
    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 [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 "[email protected]")
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 "[email protected]")
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
version: 1.2.0-{build}
branches:
  only:
  - master
  - develop
  - /^release/
  - /^support/
  - /^travis/
image:
- Visual Studio 2019
- Visual Studio 2017
- Visual Studio 2015
build_script:
- cmd: >-
|





<







1
2
3
4
5
6

7
8
9
10
11
12
13
version: 1.3.0-{build}
branches:
  only:
  - master
  - develop
  - /^release/

  - /^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
}
#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_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







>
>
>
>
>
>







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
{
   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);
}
#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_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)) {
      return MP_VAL;
   }
   return mp_expt_u32(a, (uint32_t)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)) {
      return MP_VAL;
   }
   return mp_expt_u32(a, (uint32_t)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)) {
      return MP_VAL;
   }
   return mp_root_u32(a, (uint32_t)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)) {
      return MP_VAL;
   }
   return mp_root_u32(a, (uint32_t)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);
}







|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>
>
>
>
>
>
>
>
>
>
>
>
>





|


|





|


|
>
>
>
>
>
>
>
>
>






|


|





|


|
>
>
>
>
>
>







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
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 (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, INT_MAX)) {
      return MP_VAL;
   }
   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, INT_MAX)) {
      return MP_VAL;
   }
   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, INT_MAX)) {
      return MP_VAL;
   }
   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, INT_MAX)) {
      return MP_VAL;
   }
   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
#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;





   /* 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;













>
>
>
>







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
      if (c != NULL) {
         mp_zero(c);
      }
      return err;
   }

   /* init our temps */
   if ((err = mp_init_multi(&ta, &tb, &tq, &q, 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;







|







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, (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
      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);
   return err;
}

#else

/* integer signed division.
 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]







|







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, (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
      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);
   }

   /* no easy answer [c'est la vie].  Just division */
   if ((err = mp_init_size(&q, a->used)) != MP_OKAY) {
      return err;
   }








|
|







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(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
      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) {
         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);
      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);







|
















|







22
23
24
25
26
27
28
29
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, (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, (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
#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) {
      return err;
   }

   /* initialize, (u1,u2,u3) = (1,0,a) */
   mp_set(&u1, 1uL);
   if ((err = mp_copy(a, &u3)) != MP_OKAY)                        goto LBL_ERR;














|







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, (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
   }
   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);
   return err;
}
#endif







|



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, (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
#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 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










>
>
>
>







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
#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)
{





   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;
   }








>
>
>
>
>







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
#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) {
      return err;
   }

   /* t1 = get the GCD of the two inputs */
   if ((err = mp_gcd(a, b, &t1)) != MP_OKAY) {
      goto LBL_T;
   }












|







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, (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
      err = mp_mul(a, &t2, c);
   }

   /* fix the sign to positive */
   c->sign = MP_ZPOS;

LBL_T:
   mp_clear_multi(&t1, &t2, NULL);
   return err;
}
#endif







|



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, (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
   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
        * 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);







|







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 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
#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;





   /* copy */
   if (a != c) {
      if ((err = mp_copy(a, c)) != MP_OKAY) {
         return err;
      }
   }










>
>
>
>







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
   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) {
      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)) {







|







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, (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
   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);
   return err;
}

#endif
#endif







|





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, (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

   /* 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);




   /* we need a buffer of bsize bytes */
   tmp = (unsigned char *) MP_MALLOC((size_t)bsize);
   if (tmp == NULL) {
      return MP_MEM;
   }








|
>
>
>







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);
   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
   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) {
      return err;
   }

   D = 5;
   sign = 1;

   for (;;) {







|







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,
                            (void *)NULL)) != MP_OKAY) {
      return err;
   }

   D = 5;
   sign = 1;

   for (;;) {
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);
   return err;
}
#endif
#endif
#endif







|





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, (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
   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);

   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)) {
      a->sign = MP_NEG;
   }

   return MP_OKAY;
}
#else
/* pragma message() not supported by several compilers (in mostly older but still used versions) */







|













|







12
13
14
15
16
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 & ((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) != 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
#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 <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 */






>







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
      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) {
      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
    */







|







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, (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
      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);
   return err;
}

#endif







|




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, (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

   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) {
      mp_clear(&a0);
      return err;
   }

   /* Make sure that A is the larger one*/
   if (len_a < len_b) {
      B = *a;







|







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, (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
      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);
   return err;
}
#endif







|



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, (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

   /* 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) {
      return err;
   }

   /* x == modulus, y == value to invert */
   if ((err = mp_copy(b, &x)) != MP_OKAY)                         goto LBL_ERR;

   /* we need y = |a| */







|







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, (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
   }

   mp_exch(&D, c);
   c->sign = neg;
   err = MP_OKAY;

LBL_ERR:
   mp_clear_multi(&x, &y, &u, &v, &B, &D, NULL);
   return err;
}
#endif







|



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, (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
   /* 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) {
      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;








|







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, (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
      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);
   return err;
}
#endif







|



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, (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
{
   mp_int  t;
   mp_err  err;
   int     pa, pb, ix, iy;
   mp_digit u;
   mp_word r;
   mp_digit tmpx, *tmpt, *tmpy;





   /* 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);
   }








>
>
>
>







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
 */
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;





   /* grow the destination as required */
   if (c->alloc < digs) {
      if ((err = mp_grow(c, digs)) != MP_OKAY) {
         return err;
      }
   }







>
>
>
>







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
{
   mp_int   t;
   int      pa, pb, ix, iy;
   mp_err   err;
   mp_digit u;
   mp_word  r;
   mp_digit tmpx, *tmpt, *tmpy;





   /* 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);
   }







>
>
>
>







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
#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
 * 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;





   /* grow the destination as required */
   pa = a->used + b->used;
   if (c->alloc < pa) {
      if ((err = mp_grow(c, pa)) != MP_OKAY) {
         return err;
      }





|














>
>
>
>







1
2
3
4
5
6
7
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
 * 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
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) {
      return err;
   }

   /* B */
   B = MP_MIN(a->used, b->used) / 3;

   /** a = a2 * x^2 + a1 * x + a0; */







|







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, (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
   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;

   /** 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;








|







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 = 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
LBL_ERRb0:
   mp_clear(&a2);
LBL_ERRa2:
   mp_clear(&a1);
LBL_ERRa1:
   mp_clear(&a0);
LBL_ERRa0:
   mp_clear_multi(&S1, &S2, &T1, NULL);
   return err;
}

#endif







|




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, (void *)NULL);
   return err;
}

#endif

Changes to libtommath/changes.txt.












1
2
3
4
5
6
7











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.
>
>
>
>
>
>
>
>
>
>
>







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
          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
          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







|







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 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
    }
    else {
      die "patch_file failed: " . substr($v, 0, 30) . "..";
    }
  }
  return $content;
}




















sub process_makefiles {
  my $write = shift;
  my $changed_count = 0;


  my @o = map { my $x = $_; $x =~ s/\.c$/.o/; $x } bsd_glob("*.c");
  my @all = bsd_glob("*.{c,h}");

  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 /) {
    my $old = read_file($m);
    my $new = $m eq 'makefile.msvc' ? patch_file($old, $var_obj)

                                    : patch_file($old, $var_o);

    if ($old ne $new) {
      write_file($m, $new) if $write;
      warn "changed: $m\n";
      $changed_count++;
    }
  }








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
>
|
|


















|


>
|
>







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
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 } @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 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);

    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
                my $a = $&;
                next if $a eq "mp_err";
                $a =~ tr/[a-z]/[A-Z]/;
                $a = 'BN_' . $a . '_C';
                push @deps, $a;
            }
        }





        @deps = sort(@deps);
        foreach my $a (@deps) {
            if ($list !~ /$a/) {
                print {$class} "#   define $a\n";
            }
            $list = $list . ',' . $a;
        }







>
>
>
>
>







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
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));



    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







>
>







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
prefix=@to-be-replaced@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

Name: LibTomMath
Description: public domain library for manipulating large integer numbers
Version: @to-be-replaced@
Libs: -L${libdir} -ltommath
Cflags: -I${includedir}
|
|
<
|



|


1
2

3
4
5
6
7
8
9
prefix=@CMAKE_INSTALL_PREFIX@
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@

includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@

Name: LibTomMath
Description: public domain library for manipulating large integer numbers
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
		<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"







<
<
<
<







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_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
			>
		</File>
		<File
			RelativePath="bn_mp_exch.c"
			>
		</File>
		<File
			RelativePath="bn_mp_expt_u32.c"
			>
		</File>
		<File
			RelativePath="bn_mp_exptmod.c"
			>
		</File>
		<File







|







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_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
		<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"







<
<
<
<












<
<
<
<







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_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_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
		<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"







<
<
<
<







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_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
		<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"







<
<
<
<







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_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
			>
		</File>
		<File
			RelativePath="bn_mp_lcm.c"
			>
		</File>
		<File
			RelativePath="bn_mp_log_u32.c"
			>
		</File>
		<File
			RelativePath="bn_mp_lshd.c"
			>
		</File>
		<File







|







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_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
			>
		</File>
		<File
			RelativePath="bn_mp_reduce_setup.c"
			>
		</File>
		<File
			RelativePath="bn_mp_root_u32.c"
			>
		</File>
		<File
			RelativePath="bn_mp_rshd.c"
			>
		</File>
		<File







|







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_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
		<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"







<
<
<
<












<
<
<
<







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_u32.c"
			>
		</File>
		<File
			RelativePath="bn_mp_set_u64.c"
			>
		</File>
		<File
			RelativePath="bn_mp_set_ul.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
		<File
			RelativePath="bn_s_mp_add.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_balance_mul.c"
			>




		</File>
		<File
			RelativePath="bn_s_mp_exptmod.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_exptmod_fast.c"







>
>
>
>







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
		<File
			RelativePath="bn_s_mp_karatsuba_mul.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_karatsuba_sqr.c"
			>












		</File>
		<File
			RelativePath="bn_s_mp_montgomery_reduce_fast.c"
			>
		</File>
		<File
			RelativePath="bn_s_mp_mul_digs.c"







>
>
>
>
>
>
>
>
>
>
>
>







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

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_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_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

#END_INS

$(LIBNAME):  $(OBJECTS)
	$(AR) $(ARFLAGS) $@ $(OBJECTS)
	$(RANLIB) $@








|
|

|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|







25
26
27
28
29
30
31
32
33
34
35
36
37

38
39
40
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_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_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_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
.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: clean 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







>
>
>
>
|







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: 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
# 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


AR        = ar
ARFLAGS   = r
RANLIB    = ranlib
STRIP     = strip


CFLAGS    = -O2
LDFLAGS   =

#Compilation flags
LTM_CFLAGS  = -I. $(CFLAGS)
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_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_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

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)
	$(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














|
>
>



|
>
>




|











|
|

|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|




















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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        = i686-w64-mingw32-gcc
#CC        = x86_64-w64-mingw32-clang
#CC        = aarch64-w64-mingw32-clang
AR        = ar
ARFLAGS   = r
RANLIB    = ranlib
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) -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_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_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_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 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
#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_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_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_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

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)








|
|

|
|
|
<
|
|
|
|
|
|
>
|
|
|
|
<
|
|
|
|
>
|
|
|
|







20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
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_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_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_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_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

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_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_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

#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

	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







|
|

|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|


















|
>







22
23
24
25
26
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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_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_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_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),' -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
CC        = cc
AR        = ar
ARFLAGS   = r
RANLIB    = ranlib
CFLAGS    = -O2
LDFLAGS   =

VERSION   = 1.2.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_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_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

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)








|











|
|

|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44
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.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_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_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_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
#
# Include makefile for libtommath
#

#version of library
VERSION=1.2.0
VERSION_PC=1.2.0
VERSION_SO=3:0:2

PLATFORM := $(shell uname | sed -e 's/_.*//')

# default make target
default: ${LIBNAME}

# Compiler and Linker Names





|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#
# Include makefile for libtommath
#

#version of library
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
  _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_APP = ./test && ./timing
else
   COVERAGE = test
   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)







|


|















<
<
<
<







112
113
114
115
116
117
118
119
120
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_standalone timing
   COVERAGE_APP = ./test && ./timing
else
   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





#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
    mp_div_3
    mp_div_d
    mp_dr_is_modulus
    mp_dr_reduce
    mp_dr_setup
    mp_error_to_string
    mp_exch

    mp_expt_u32
    mp_exptmod
    mp_exteuclid
    mp_fread
    mp_from_sbin
    mp_from_ubin
    mp_fwrite







>







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
    mp_init_ull
    mp_invmod
    mp_is_square
    mp_iseven
    mp_isodd
    mp_kronecker
    mp_lcm

    mp_log_u32
    mp_lshd
    mp_mod
    mp_mod_2d
    mp_mod_d
    mp_montgomery_calc_normalization
    mp_montgomery_reduce







>







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
    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_u32
    mp_rshd
    mp_sbin_size
    mp_set
    mp_set_double
    mp_set_i32
    mp_set_i64







>







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












    mp_to_radix
    mp_to_sbin
    mp_to_ubin
    mp_ubin_size
    mp_unpack
    mp_xor
    mp_zero



















>
>
>
>
>
>
>
>
>
>
>
>
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
/* 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>
#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






<
<
|
<







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_



#include <stdint.h>

#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

/* 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) || \
    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)
/* 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







|






|







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) || 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(__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
#  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_PRAGMA(s) __pragma(message(s))
#endif
#endif

#ifndef MP_DEPRECATED_PRAGMA
#  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)







<
<
<
<
<
<
<
<



>

|
<
<
|







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)))








#  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))
#else


#  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
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;
#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;

/* 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;
#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;
#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);
#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;







<
<
<
|
<











<

<
<
<
<
<
<
<
<
<
<
|
|
|


|
|
|
<








<
|
<


<
|
<







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;



MP_DEPRECATED(mp_get_mag_u64) unsigned long long mp_get_mag_ull(const mp_int *a) MP_WUR;


/* 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;


/* get integer, set integer (long long) */










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) (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;


/* 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;

MP_DEPRECATED(mp_get_mag_u64/mp_get_u64) unsigned long long mp_get_long_long(const mp_int *a) MP_WUR;

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);

MP_DEPRECATED(mp_set_ull) mp_err mp_set_long_long(mp_int *a, unsigned long long b);

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
/* 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;

/* 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;








|







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_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

/* 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;











/* 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_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;

/* 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;








>
>
>
>
>
>
>
>
>
>




>
|
|
|







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_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
 * 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;







<
<
<
<
<
<
<
<







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;









/* ---> 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
#   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_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_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







<






|











<



<







<






<






|







29
30
31
32
33
34
35

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

54
55
56

57
58
59
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_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_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_MAG_U32_C
#   define BN_MP_GET_MAG_U64_C
#   define BN_MP_GET_MAG_UL_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_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_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_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
#   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_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_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_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







|







<



<



















>







>
>
>







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

121
122
123

124
125
126
127
128
129
130
131
132
133
134
135
136
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_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_U32_C
#   define BN_MP_SET_U64_C
#   define BN_MP_SET_UL_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
#   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_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_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_LONG_C
#   define BN_MP_GET_LONG_LONG_C
#   define BN_MP_GET_MAG_U32_C

#   define BN_MP_GET_MAG_ULL_C
#   define BN_MP_GET_MAG_UL_C
#   define BN_MP_IMPORT_C

#   define BN_MP_INIT_SET_INT_C
#   define BN_MP_INIT_U32_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_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_U32_C
#   define BN_MP_SBIN_SIZE_C
#   define BN_MP_SET_INT_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_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







>




>





>



>



>


>





>
>









>



>




>







175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
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
#   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_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







>







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
#   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
#endif

#if defined(BN_MP_DR_IS_MODULUS_C)
#endif

#if defined(BN_MP_DR_REDUCE_C)
#   define BN_MP_CLAMP_C







<
<
<
<
<
<
<





|
|
|







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_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_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

#if defined(BN_MP_ERROR_TO_STRING_C)
#endif

#if defined(BN_MP_EXCH_C)
#endif

#if defined(BN_MP_EXPT_U32_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








|







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_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
#   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







<
<
<
<









<
<
<







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_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_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
#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







<
<
<
<
<







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_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
#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)







<
<
<
<
<







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_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
#   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)
#   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_COUNT_BITS_C
#   define BN_MP_EXCH_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)







|
<
|
<
|
<
|
<
<
<
<
<







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_N_C)

#   define BN_S_MP_LOG_2EXPT_C

#   define BN_S_MP_LOG_C

#   define BN_S_MP_LOG_D_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
#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)
#   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_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







|








|







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_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_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
#   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







<
<
<
<









<
<
<







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_U32_C)
#endif

#if defined(BN_MP_SET_U64_C)
#endif

#if defined(BN_MP_SET_UL_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
#   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_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







>
>
>
>
>
>
>







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
#   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_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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

#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

#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







<






>







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_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
/* 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>


#else
#  include "../compat/stdint.h"
#endif
#endif
#include "tclTomMath.h"
#include "tommath_class.h"

/*
 * Private symbols
 * ---------------
 *
 * On Unix symbols can be marked as hidden if libtommath is compiled






<
<
|
>
>

|

<
<







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_



#include <stdint.h>
#ifndef TCL_WITH_EXTERNAL_TOMMATH
# include "tclTomMath.h"
#else
# include "tommath.h"
#endif


#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
#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))



/* 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))







>
>







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
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 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_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_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;







>
>


>
















>







192
193
194
195
196
197
198
199
200
201
202
203
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
########################################################################################################
#
# 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
#	if you are not using the tk/macosx projects).
#
# Copyright (c) 2002-2008 Daniel A. Steffen <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.
########################################################################################################



|







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
#	if you are not using the tk/macosx projects).
#
# Copyright (c) 2002-2008 Daniel A. Steffen <[email protected]>
#
# 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
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 \
			   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}))







|







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-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
	${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 \
	${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi

build-${PROJECT}: ${objdir}/Makefile
	${DO_MAKE}
ifeq (${INSTALL_BUILD},)
# symolic 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








|





|







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 --disable-zipfs \
	${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi

build-${PROJECT}: ${objdir}/Makefile
	${DO_MAKE}
ifeq (${INSTALL_BUILD},)
# 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.

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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"
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
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
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"
	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







<












<

<



<
<








|








|
<
|
<

|
<












<
<


|







76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
91
92
93
94

95

96
97
98


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

117

118
119

120
121
122
123
124
125
126
127
128
129
130
131


132
133
134
135
136
137
138
139
140
141
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.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.

	DebugNoCF:		    disable corefoundation.

	DebugMemCompile:	    enable memory and bytecode debugging.
	DebugLeaks:		    define PURIFY.
	DebugGCov:		    enable generation of gcov data files.


	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.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 x86_64 -arch arm64"

This requires Mac OS X 10.6 and Xcode 10.2 and will work on any architecture.

Note that configure requires CFLAGS to contain a least one architecture that can
be run on the build machine (i.e. 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"



- Setup environment variables as desired, e.g. for a universal build on 10.5:
	CFLAGS="-arch x86_64 -arch arm64 -mmacosx-version-min=10.5"
	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

Changes to macosx/Tcl-Common.xcconfig.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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







|







<
<






15
16
17
18
19
20
21
22
23
24
25
26
27
28
29


30
31
32
33
34
35
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 -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


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

Changes to macosx/Tcl-Release.xcconfig.

10
11
12
13
14
15
16
17
18
19
20
// 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







|



10
11
12
13
14
15
16
17
18
19
20
// 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 = 2
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 <[email protected]>\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 */;
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































Changes to macosx/Tcl.xcodeproj/project.pbxproj.

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
		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 */; };







|







106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
		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_s_mp_div_3.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427908F272B3004A47F5 /* bn_s_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 */; };
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
		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 */; };







|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
		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_n.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D427F08F272B3004A47F5 /* bn_mp_expt_n.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 */; };
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
		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>"; };







<
|


















<







219
220
221
222
223
224
225

226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
		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>"; };

		F96D3DFB08F272A4004A47F5 /* changes.md */ = {isa = PBXFileReference; explicitFileType = text; fileEncoding = 4; path = changes.md; 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>"; };

		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>"; };
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
		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>"; };







|
















|







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
		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 /* SaveInterpState.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = SaveInterpState.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 /* StaticLibrary.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; path = StaticLibrary.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>"; };
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
		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>"; };







|


|







565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
		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_s_mp_div_3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_s_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_n.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bn_mp_expt_n.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>"; };
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
		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>"; };







<
<
<
<
<
<


<







764
765
766
767
768
769
770






771
772

773
774
775
776
777
778
779
		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>"; };






		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>"; };

		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>"; };
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
		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>"; };







<







825
826
827
828
829
830
831

832
833
834
835
836
837
838
		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>"; };

		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>"; };
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
				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;







<
|
|







944
945
946
947
948
949
950

951
952
953
954
955
956
957
958
959
				F96D425C08F272B2004A47F5 /* libtommath */,
				F96D446E08F272B9004A47F5 /* win */,
				F96D3F3808F272A7004A47F5 /* library */,
				F96D434408F272B5004A47F5 /* tests */,
				F96D3DFC08F272A4004A47F5 /* doc */,
				F96D43D008F272B8004A47F5 /* tools */,
				F9183E690EFC81560030B814 /* pkgs */,

				F96D3DFB08F272A4004A47F5 /* changes.md */,
				F96D434308F272B5004A47F5 /* README.md */,
				F96D432B08F272B4004A47F5 /* license.terms */,
			);
			name = "Tcl Sources";
			sourceTree = TCL_SRCROOT;
		};
		F96D3DFC08F272A4004A47F5 /* doc */ = {
			isa = PBXGroup;
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
				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 */,







<







972
973
974
975
976
977
978

979
980
981
982
983
984
985
				F96D3E0808F272A5004A47F5 /* Backslash.3 */,
				F96D3E0908F272A5004A47F5 /* bgerror.n */,
				F96D3E0A08F272A5004A47F5 /* binary.n */,
				F96D3E0B08F272A5004A47F5 /* BoolObj.3 */,
				F96D3E0C08F272A5004A47F5 /* break.n */,
				F96D3E0D08F272A5004A47F5 /* ByteArrObj.3 */,
				F96D3E0E08F272A5004A47F5 /* CallDel.3 */,

				F96D3E1008F272A5004A47F5 /* catch.n */,
				F96D3E1108F272A5004A47F5 /* cd.n */,
				F96D3E1208F272A5004A47F5 /* chan.n */,
				F96D3E1308F272A5004A47F5 /* ChnlStack.3 */,
				F93599CF0DF1F87F00E04F67 /* Class.3 */,
				F93599D00DF1F89E00E04F67 /* class.n */,
				F96D3E1408F272A5004A47F5 /* clock.n */,
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
				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 */,







|

















|







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
				F96D3E8D08F272A6004A47F5 /* RegExp.3 */,
				F96D3E8E08F272A6004A47F5 /* regexp.n */,
				F96D3E8F08F272A6004A47F5 /* registry.n */,
				F96D3E9008F272A6004A47F5 /* regsub.n */,
				F96D3E9108F272A6004A47F5 /* rename.n */,
				F96D3E9208F272A6004A47F5 /* return.n */,
				F96D3E9308F272A6004A47F5 /* safe.n */,
				F96D3E9408F272A6004A47F5 /* SaveInterpState.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 /* StaticLibrary.3 */,
				F96D3EA608F272A7004A47F5 /* StdChannels.3 */,
				F96D3EA708F272A7004A47F5 /* string.n */,
				F96D3EA808F272A7004A47F5 /* StringObj.3 */,
				F96D3EA908F272A7004A47F5 /* StrMatch.3 */,
				F96D3EAA08F272A7004A47F5 /* subst.n */,
				F96D3EAB08F272A7004A47F5 /* SubstObj.3 */,
				F96D3EAC08F272A7004A47F5 /* switch.n */,
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
				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 */,







|


|







1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
				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_s_mp_div_3.c */,
				F96D427A08F272B3004A47F5 /* bn_mp_div_d.c */,
				F96D427E08F272B3004A47F5 /* bn_mp_exch.c */,
				F96D427F08F272B3004A47F5 /* bn_mp_expt_n.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 */,
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
			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;







<
<




<

<
<
<
<
<
<


<







1627
1628
1629
1630
1631
1632
1633


1634
1635
1636
1637

1638






1639
1640

1641
1642
1643
1644
1645
1646
1647
			path = tests;
			sourceTree = "<group>";
		};
		F96D43D008F272B8004A47F5 /* tools */ = {
			isa = PBXGroup;
			children = (
				F96D43D108F272B8004A47F5 /* checkLibraryDoc.tcl */,


				F96D442508F272B8004A47F5 /* genStubs.tcl */,
				F96D442708F272B8004A47F5 /* index.tcl */,
				F96D442808F272B8004A47F5 /* installData.tcl */,
				F96D442908F272B8004A47F5 /* loadICU.tcl */,

				F96D442B08F272B8004A47F5 /* makeTestCases.tcl */,






				F96D443208F272B8004A47F5 /* README */,
				F96D443308F272B8004A47F5 /* regexpTestLib.tcl */,

				F96D443908F272B9004A47F5 /* tcltk-man2html.tcl */,
				F96D443A08F272B9004A47F5 /* tclZIC.tcl */,
				F92D7F100DE777240033A13A /* tsdPerf.tcl */,
				F96D443B08F272B9004A47F5 /* uniClass.tcl */,
				F96D443C08F272B9004A47F5 /* uniParse.tcl */,
			);
			path = tools;
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
				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 */,







<







1718
1719
1720
1721
1722
1723
1724

1725
1726
1727
1728
1729
1730
1731
				F96D447808F272BA004A47F5 /* makefile.vc */,
				F96D447908F272BA004A47F5 /* nmakehlp.c */,
				F96D447A08F272BA004A47F5 /* README */,
				F96D447C08F272BA004A47F5 /* rules.vc */,
				F96D447D08F272BA004A47F5 /* stub16.c */,
				F96D447E08F272BA004A47F5 /* tcl.dsp */,
				F96D447F08F272BA004A47F5 /* tcl.dsw */,

				F96D448108F272BA004A47F5 /* tcl.m4 */,
				F96D448208F272BA004A47F5 /* tcl.rc */,
				F96D448308F272BA004A47F5 /* tclAppInit.c */,
				F96D448408F272BA004A47F5 /* tclConfig.sh.in */,
				F96D448608F272BA004A47F5 /* tclsh.rc */,
				F96D448708F272BA004A47F5 /* tclWin32Dll.c */,
				F96D448808F272BA004A47F5 /* tclWinChan.c */,
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
				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 */,







|


|







2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
				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_s_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_n.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 */,
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
			};
			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;







|
|







2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
			};
			name = ReleaseUniversal;
		};
		F91BCC51093152310042A6BF /* ReleaseUniversal */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
				CFLAGS = "-arch x86_64 -arch arm64 $(CFLAGS)";
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				PREBINDING = NO;
			};
			name = ReleaseUniversal;
		};
		F93084370BB93D2800CD0B9E /* DebugMemCompile */ = {
			isa = XCBuildConfiguration;
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
				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)",







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2351
2352
2353
2354
2355
2356
2357






































2358
2359
2360
2361
2362
2363
2364
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = ReleaseUniversal;
		};






































		F987512F0DE7B57E00B1C9EC /* DebugNoCF */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
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
				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)",







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







2393
2394
2395
2396
2397
2398
2399










































2400
2401
2402
2403
2404
2405
2406
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = DebugNoCF;
		};










































		F9988AB10D814C6500B6B03B /* Debug gcc40 */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
			};
			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 */ = {







|
|







2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
			};
			name = "Debug llvm-gcc";
		};
		F9988BB10D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
				CFLAGS = "-arch x86_64 -arch arm64 $(CFLAGS)";
				GCC_VERSION = 4.0;
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				PREBINDING = NO;
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB20D81586D00B6B03B /* ReleaseUniversal gcc40 */ = {
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
			};
			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 */ = {







|
|



<







2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547

2548
2549
2550
2551
2552
2553
2554
			};
			name = "ReleaseUniversal gcc40";
		};
		F9988BB50D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
				CFLAGS = "-arch x86_64 -arch arm64 $(CFLAGS)";
				DEBUG_INFORMATION_FORMAT = dwarf;
				GCC = "llvm-gcc";
				GCC_OPTIMIZATION_LEVEL = 4;

				GCC_VERSION = com.apple.compilers.llvmgcc42;
				MACOSX_DEPLOYMENT_TARGET = 10.6;
				PREBINDING = NO;
			};
			name = "ReleaseUniversal llvm-gcc";
		};
		F9988BB60D81587400B6B03B /* ReleaseUniversal llvm-gcc */ = {
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
				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)",







<
<
<
<
<
<
<
<








<
<
<
<
<
<
<







<
<
<
<
<
<
<
<
<
<
<











<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
				PRODUCT_NAME = tests;
				TCLTEST_OPTIONS = "";
				TCL_LIBRARY = "$(TCL_SRCROOT)/library";
				TEST_RIG = "$(OBJROOT)/$(CONFIGURATION)/tcltest";
			};
			name = "ReleaseUniversal llvm-gcc";
		};








		F99EE73C0BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tclsh;
				SKIP_INSTALL = NO;
			};
			name = DebugLeaks;
		};







		F99EE73E0BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				PRODUCT_NAME = tcltest;
			};
			name = DebugLeaks;
		};











		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;
		};
















		F99EE7420BE835310060D4AF /* DebugLeaks */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Tcl-Debug.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",
					"$(NATIVE_ARCH_32_BIT)",
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
		};
		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;
			};







<

|







2676
2677
2678
2679
2680
2681
2682

2683
2684
2685
2686
2687
2688
2689
2690
2691
		};
		F9A9D1F30FC77799002A2BE3 /* ReleaseUniversal clang */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = (
					"$(NATIVE_ARCH_64_BIT)",

				);
				CFLAGS = "-arch x86_64 -arch arm64 $(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;
			};
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
			};
			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 */,
			);







|
|


















<

<



<


















<

<



<


















<

<



<


















<

<



<







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
			};
			name = ReleaseUniversal10.5SDK;
		};
		F9EEED990C2FEFD300396116 /* ReleaseUniversal10.5SDK */ = {
			isa = XCBuildConfiguration;
			baseConfigurationReference = F97AE82B0B65C69B00310EA2 /* Tcl-Release.xcconfig */;
			buildSettings = {
				ARCHS = "$(ARCHS_STANDARD_64_BIT)";
				CFLAGS = "-arch x86_64 -arch arm64 $(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 */,

				F98751300DE7B57E00B1C9EC /* DebugNoCF */,

				F93084370BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE73C0BE835310060D4AF /* DebugLeaks */,
				F9359B260DF212DA00E04F67 /* DebugGCov */,

				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 */,

				F98751310DE7B57E00B1C9EC /* DebugNoCF */,

				F93084380BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE73E0BE835310060D4AF /* DebugLeaks */,
				F9359B270DF212DA00E04F67 /* DebugGCov */,

				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 */,

				F987512F0DE7B57E00B1C9EC /* DebugNoCF */,

				F930843A0BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE7420BE835310060D4AF /* DebugLeaks */,
				F9359B250DF212DA00E04F67 /* DebugGCov */,

				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 */,

				F98751320DE7B57E00B1C9EC /* DebugNoCF */,

				F93084390BB93D2800CD0B9E /* DebugMemCompile */,
				F99EE7400BE835310060D4AF /* DebugLeaks */,
				F9359B280DF212DA00E04F67 /* DebugGCov */,

				F97258AA0A86873D00096C78 /* Release */,
				F97258AC0A86873D00096C78 /* ReleaseUniversal */,
				F9A9D1F60FC77799002A2BE3 /* ReleaseUniversal clang */,
				F9988BB80D81587400B6B03B /* ReleaseUniversal llvm-gcc */,
				F9988BB40D81586D00B6B03B /* ReleaseUniversal gcc40 */,
				F9EEED980C2FEFD300396116 /* ReleaseUniversal10.5SDK */,
			);

Changes to macosx/tclMacOSXBundle.c.

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 <[email protected]>
 *
 * 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"






|
|







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 © 2003-2009 Daniel A. Steffen <[email protected]>
 *
 * 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

int
Tcl_MacOSXOpenVersionedBundleResources(
    TCL_UNUSED(Tcl_Interp *),
    const char *bundleName,
    const char *bundleVersion,
    int hasResourceFile,
    size_t maxPathLen,
    char *libraryPath)
{
#ifdef HAVE_COREFOUNDATION
    CFBundleRef bundleRef, versionedBundleRef = NULL;
    CFStringRef bundleNameRef;
    CFURLRef libURL;








|







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,
    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
/*
 * tclMacOSXFCmd.c
 *
 *	This file implements the MacOSX specific portion of file manipulation
 *	subcommands of the "file" command.
 *
 * Copyright (c) 2003-2007 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|







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 © 2003-2007 Daniel A. Steffen <[email protected]>
 *
 * 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
static void		UpdateStringOfOSType(Tcl_Obj *objPtr);

static const Tcl_ObjType tclOSTypeType = {
    "osType",				/* name */
    NULL,				/* freeIntRepProc */
    NULL,				/* dupIntRepProc */
    UpdateStringOfOSType,		/* updateStringProc */
    SetOSTypeFromAny			/* setFromAnyProc */

};

enum {
    kIsInvisible = 0x4000,
};

#define kFinfoIsInvisible	(OSSwapHostToBigConstInt16(kIsInvisible))







|
>







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 */
    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
    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);
    return TCL_ERROR;
#endif /* HAVE_GETATTRLIST */
}

/*
 *---------------------------------------------------------------------------
 *







|
|







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", 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
	    /*
	     * 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);
		return TCL_ERROR;
	    }

	    /*
	     * Construct path to resource fork.
	     */

	    Tcl_DStringInit(&ds);
	    Tcl_DStringAppend(&ds, native, -1);
	    Tcl_DStringAppend(&ds, _PATH_RSRCFORKSPEC, -1);

	    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:







|
|








|
|







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", 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, 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
		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);
    return TCL_ERROR;
#endif
}

/*
 *---------------------------------------------------------------------------
 *







|
|







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", 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
	}

	/*
	 * Construct paths to resource forks.
	 */

	Tcl_DStringInit(&srcBuf);
	Tcl_DStringAppend(&srcBuf, src, -1);
	Tcl_DStringAppend(&srcBuf, _PATH_RSRCFORKSPEC, -1);
	Tcl_DStringInit(&dstBuf);
	Tcl_DStringAppend(&dstBuf, dst, -1);
	Tcl_DStringAppend(&dstBuf, _PATH_RSRCFORKSPEC, -1);

	/*
	 * Do the copy.
	 */

	result = TclUnixCopyFile(Tcl_DStringValue(&srcBuf),
		Tcl_DStringValue(&dstBuf), statBufPtr, 1);







|
|

|
|







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, TCL_INDEX_NONE);
	Tcl_DStringAppend(&srcBuf, _PATH_RSRCFORKSPEC, TCL_INDEX_NONE);
	Tcl_DStringInit(&dstBuf);
	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
 * 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
 *	case an error is left in interp).
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */







|







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 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
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)) {
	result = SetOSTypeFromAny(interp, objPtr);
    }
    *osTypePtr = (OSType) objPtr->internalRep.wideValue;
    return result;
}

/*







|







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 (!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
    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;

    string = TclGetStringFromObj(objPtr, &length);
    Tcl_UtfToExternalDString(encoding, string, length, &ds);

    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);
	}
	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);
	objPtr->internalRep.wideValue = (Tcl_WideInt) osType;
	objPtr->typePtr = &tclOSTypeType;
    }
    Tcl_DStringFree(&ds);
    Tcl_FreeEncoding(encoding);
    return result;
}







|


|





|











|







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");
    Tcl_Size length;

    string = TclGetStringFromObj(objPtr, &length);
    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", (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];
	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
    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,
	    /* statePtr */ NULL, dst, size, /* srcReadPtr */ NULL,
	    /* dstWrotePtr */ &written, /* dstCharsPtr */ NULL);
    Tcl_FreeEncoding(encoding);

    (void)Tcl_InitStringRep(objPtr, NULL, written);
}








|







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, 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
/*
 * 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 <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"








|
|
|







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 © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2001-2009, Apple Inc.
 * Copyright © 2005-2009 Daniel A. Steffen <[email protected]>
 *
 * 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

/*
 * Debug version of SpinLockLock that logs the time spent waiting for the lock
 */

#define SpinLockLockDbg(p) \
    if (!SpinLockTry(p)) {						\
	Tcl_WideInt s = TclpGetWideClicks(), e;				\
									\
	SpinLockLock(p);						\
	e = TclpGetWideClicks();					\
	TclMacOSXNotifierDbgMsg("waited on %s for %8.0f ns",		\
		#p, TclpWideClicksToNanoseconds(e-s));			\
    }
#undef LOCK_NOTIFIER_INIT







|







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)) {						\
	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
    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. */
    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.
 */







|







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. */
    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
 * The following static indicates if the notifier thread is running.
 *
 * You must hold the notifierInitLock before accessing this variable.
 */

static int notifierThreadRunning;















/*
 * 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.
 */








>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
#define CF_TIMEINTERVAL_FOREVER 5.05e8

/*
 * Static routines defined in this file.
 */

static void		StartNotifierThread(void);
static TCL_NORETURN void NotifierThreadProc(ClientData 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,







|







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(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
#define noCFafterFork	1
#endif /* MAC_OS_X_VERSION_MIN_REQUIRED */
#endif /* HAVE_PTHREAD_ATFORK */

/*
 *----------------------------------------------------------------------
 *



















































 * 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)
{
    ThreadSpecificData *tsdPtr;

    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");
    }
#endif

#ifndef __CONSTANT_CFSTRINGS__
    if (!tclEventsOnlyRunLoopMode) {
	tclEventsOnlyRunLoopMode = CFSTR(TCL_EVENTS_ONLY_RUN_LOOP_MODE);
    }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|












|
|

|
<
<
<
<
<
<






|







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;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpInitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpInitNotifier(void)
{
    ThreadSpecificData *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: %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

	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");

	}
	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");
	}
	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");
	}
	CFRunLoopAddObserver(runLoop, runLoopObserverTcl,
		tclEventsOnlyRunLoopMode);

	tsdPtr->runLoop = runLoop;
	tsdPtr->runLoopSource = runLoopSource;
	tsdPtr->runLoopObserver = runLoopObserver;







|
>











|
|
















|
|







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: %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: %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: %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
     * child of a fork.
     */

    if (MayUsePthreadAtfork() && !atForkInit) {
	int result = pthread_atfork(AtForkPrepare, AtForkParent, AtForkChild);

	if (result) {
	    Tcl_Panic("Tcl_InitNotifier: 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");
	}

	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");
	}
	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");
	}

	receivePipe = fds[0];
	triggerPipe = fds[1];

	/*
	 * Create notifier thread lazily in Tcl_WaitForEvent() to avoid







|












|





|
|




|
|







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: %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: %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: %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: %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
    UNLOCK_NOTIFIER_INIT;
    return tsdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * TclMacOSXNotifierAddRunLoopMode --
 *
 *	Add the tcl notifier RunLoop source, observer and timer (if any)
 *	to the given RunLoop mode.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TclMacOSXNotifierAddRunLoopMode(
    const void *runLoopMode)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    CFStringRef mode = (CFStringRef) runLoopMode;

    if (tsdPtr->runLoop) {
	CFRunLoopAddSource(tsdPtr->runLoop, tsdPtr->runLoopSource, mode);







|














|







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;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_MacOSXNotifierAddRunLoopMode --
 *
 *	Add the tcl notifier RunLoop source, observer and timer (if any)
 *	to the given RunLoop mode.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
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
    if (!notifierCount) {
	Tcl_Panic("StartNotifierThread: notifier not initialized");
    }
    if (!notifierThreadRunning) {
	int result;
	pthread_attr_t attr;










	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);
	pthread_attr_destroy(&attr);
	if (result) {
	    Tcl_Panic("StartNotifierThread: unable to start notifier thread");
	}
	notifierThreadRunning = 1;






    }
    UNLOCK_NOTIFIER_INIT;
}


/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
 *
 *	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)
{
    ThreadSpecificData *tsdPtr;

    if (tclNotifierHooks.finalizeNotifierProc) {
	tclNotifierHooks.finalizeNotifierProc(clientData);
	return;
    }

    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







>
>
>
>
>
>
>
>
>





|





>
>
>
>
>
>








|















|
<
<
<
|
<
<
<
<
|
|







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
    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);
	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;
}


/*
 *----------------------------------------------------------------------
 *
 * 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
TclpFinalizeNotifier(



    TCL_UNUSED(void *))




{
    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
		int result = pthread_join(notifierThread, NULL);

		if (result) {
		    Tcl_Panic("Tcl_FinalizeNotifier: unable to join notifier "
			    "thread");
		}
		notifierThreadRunning = 0;








	    }

	    close(receivePipe);
	    triggerPipe = -1;
	}
	CLOSE_NOTIFIER_LOG;
    }







>
>
>
>
>
>
>
>







901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
		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
    }
    UNLOCK_NOTIFIER_TSD;
}

/*
 *----------------------------------------------------------------------
 *
 * 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 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)
{
    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 --
 *
 *	This function sets the current notifier timer value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Replaces any previous timer.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimer(
    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);
	    waitTime = vTime.sec + 1.0e-6 * vTime.usec;
	} else {
	    waitTime = 0;
	}
    } else {
	waitTime = CF_TIMEINTERVAL_FOREVER;
    }







|
















|
|

|
<
<
<
<
<












|













|






<
<
<
<
<









|







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
    }
    UNLOCK_NOTIFIER_TSD;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
TclpAlertNotifier(
    void *clientData)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;






    LOCK_NOTIFIER_TSD;
    if (tsdPtr->runLoop) {
	CFRunLoopSourceSignal(tsdPtr->runLoopSource);
	CFRunLoopWakeUp(tsdPtr->runLoop);
    }
    UNLOCK_NOTIFIER_TSD;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpSetTimer --
 *
 *	This function sets the current notifier timer value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Replaces any previous timer.
 *
 *----------------------------------------------------------------------
 */

void
TclpSetTimer(
    const Tcl_Time *timePtr)		/* Timeout value, may be NULL. */
{
    ThreadSpecificData *tsdPtr;
    CFRunLoopTimerRef runLoopTimer;
    CFTimeInterval waitTime;






    tsdPtr = TCL_TSD_INIT(&dataKey);
    runLoopTimer = tsdPtr->runLoopTimer;
    if (!runLoopTimer) {
	return;
    }
    if (timePtr) {
	Tcl_Time vTime = *timePtr;

	if (vTime.sec != 0 || vTime.usec != 0) {
	    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
 *
 *----------------------------------------------------------------------
 */

static void
TimerWakeUp(
    TCL_UNUSED(CFRunLoopTimerRef),
    TCL_UNUSED(ClientData))
{
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ServiceModeHook --
 *
 *	This function is invoked whenever the service mode changes.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_ServiceModeHook(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{
    ThreadSpecificData *tsdPtr;

    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 --
 *
 *	This function registers a file handler with the select notifier.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *
 *----------------------------------------------------------------------
 */

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. */
    ClientData clientData)	/* Arbitrary data to pass to proc. */
{
    ThreadSpecificData *tsdPtr;
    FileHandler *filePtr;

    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->fd = fd;
	filePtr->readyMask = 0;
	filePtr->nextPtr = tsdPtr->firstFileHandlerPtr;
	tsdPtr->firstFileHandlerPtr = filePtr;
    }
    filePtr->proc = proc;
    filePtr->clientData = clientData;







|






|













|



|
<
<
<
<
<
<
<



















|

|











|







|

|
|

<
<
<
<
<
<
<
<
<
<
<
<
<

|







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
 *
 *----------------------------------------------------------------------
 */

static void
TimerWakeUp(
    TCL_UNUSED(CFRunLoopTimerRef),
    TCL_UNUSED(void *))
{
}

/*
 *----------------------------------------------------------------------
 *
 * TclpServiceModeHook --
 *
 *	This function is invoked whenever the service mode changes.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TclpServiceModeHook(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{
    ThreadSpecificData *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();
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpCreateFileHandler --
 *
 *	This function registers a file handler with the notifier.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *
 *----------------------------------------------------------------------
 */

void
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. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);














    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;
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
    }
    UNLOCK_NOTIFIER_TSD;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 *
 *	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(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    FileHandler *filePtr, *prevPtr;
    int i, numFdBits;
    ThreadSpecificData *tsdPtr;

    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;
	}
	if (filePtr->fd == fd) {
	    break;
	}
    }

    /*
     * Find current max fd.
     */

    if (fd+1 == tsdPtr->numFdBits) {
	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.exceptional)) {
		numFdBits = i+1;
		break;
	    }
	}
    }

    LOCK_NOTIFIER_TSD;
    if (numFdBits != -1) {







|













|




|
|
<
<
<
<
<
<
<
<





<
|
|
|
<
<
<
<






|

|



|







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
    }
    UNLOCK_NOTIFIER_TSD;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
TclpDeleteFileHandler(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    FileHandler *filePtr, *prevPtr;
    int i, numFdBits = -1;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);









    /*
     * Find the entry for the given file (and return if there isn't one).
     */


    filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
    if (filePtr == NULL) {
	return;




    }

    /*
     * Find current max fd.
     */

    if (fd + 1 == tsdPtr->numFdBits) {
	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.exceptional)) {
		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
     * 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) {
	    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







<
|
|
<
<
<







1279
1280
1281
1282
1283
1284
1285

1286
1287



1288
1289
1290
1291
1292
1293
1294
     * 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);

    filePtr = LookUpFileHandler(tsdPtr, fileEvPtr->fd, NULL);
    if (filePtr != NULL) {



	/*
	 * 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
	    }
	    if (mask & TCL_EXCEPTION) {
		FD_CLR(filePtr->fd, &tsdPtr->readyMasks.exceptional);
	    }
	    UNLOCK_NOTIFIER_TSD;
	    filePtr->proc(filePtr->clientData, mask);
	}
	break;
    }
    return 1;
}

/*
 *----------------------------------------------------------------------
 *























 * Tcl_WaitForEvent --
 *
 *	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
 *	CFRunLoop source was processed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_WaitForEvent(
    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");







<







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|






|









|







<
<
<







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
	    }
	    if (mask & TCL_EXCEPTION) {
		FD_CLR(filePtr->fd, &tsdPtr->readyMasks.exceptional);
	    }
	    UNLOCK_NOTIFIER_TSD;
	    filePtr->proc(filePtr->clientData, mask);
	}

    }
    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;
}

/*
 *----------------------------------------------------------------------
 *
 * 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 occurred and 1 if a non-tcl
 *	CFRunLoop source was processed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
TclpWaitForEvent(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
{
    int result, polling, runLoopRunning;
    CFTimeInterval waitTime;
    SInt32 runLoopStatus;
    ThreadSpecificData *tsdPtr;




    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
	/*
	 * 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);
	    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.
	     */

	    polling = 1;
	    waitTime = tsdPtr->runLoopRunning ? 0 : 0.0001;
	}
    }








|


<










|
|







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
	/*
	 * 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) {
	    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.
	     */

	    polling = 1;
	    waitTime = tsdPtr->runLoopRunning ? 0 : 0.0001;
	}
    }

1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441

static void
QueueFileEvents(
    void *info)
{
    SelectMasks readyMasks;
    FileHandler *filePtr;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)info;

    /*
     * Queue all detected file events.
     */

    LOCK_NOTIFIER_TSD;
    FD_COPY(&tsdPtr->readyMasks.readable, &readyMasks.readable);







|







1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488

static void
QueueFileEvents(
    void *info)
{
    SelectMasks readyMasks;
    FileHandler *filePtr;
    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

	/*
	 * 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));


	    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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
UpdateWaitingListAndServiceEvents(
    TCL_UNUSED(CFRunLoopObserverRef),
    CFRunLoopActivity activity,
    void *info)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)info;

    if (tsdPtr->sleeping) {
	return;
    }
    switch (activity) {
    case kCFRunLoopEntry:
	tsdPtr->runLoopNestingLevel++;
	if (tsdPtr->numFdBits > 0 || tsdPtr->polling) {







|
>














|
|
















|
>







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

	/*
	 * 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));

	    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.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
UpdateWaitingListAndServiceEvents(
    TCL_UNUSED(CFRunLoopObserverRef),
    CFRunLoopActivity activity,
    void *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

    /*
     * TIP #233: Scale from virtual time to real-time.
     */

    vdelay.sec = ms / 1000;
    vdelay.usec = (ms % 1000) * 1000;
    tclScaleTimeProcPtr(&vdelay, tclTimeClientData);


    if (tsdPtr->runLoop) {
	CFTimeInterval waitTime;
	CFRunLoopTimerRef runLoopTimer = tsdPtr->runLoopTimer;
	CFAbsoluteTime nextTimerFire = 0, waitEnd, now;
	SInt32 runLoopStatus;








<
|







1671
1672
1673
1674
1675
1676
1677

1678
1679
1680
1681
1682
1683
1684
1685

    /*
     * TIP #233: Scale from virtual time to real-time.
     */

    vdelay.sec = ms / 1000;
    vdelay.usec = (ms % 1000) * 1000;

    TclScaleTime(&vdelay);

    if (tsdPtr->runLoop) {
	CFTimeInterval waitTime;
	CFRunLoopTimerRef runLoopTimer = tsdPtr->runLoopTimer;
	CFAbsoluteTime nextTimerFire = 0, waitEnd, now;
	SInt32 runLoopStatus;

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
    }
    return result;
}

/*
 *----------------------------------------------------------------------
 *























































 * 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.
 *
 * 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))
{
    ThreadSpecificData *tsdPtr;
    fd_set readableMask, writableMask, exceptionalMask;
    int i, numFdBits = 0, polling;
    struct timeval poll = {0., 0.}, *timePtr;
    char buf[2];

    /*
     * Look for file events and report them to interested threads.
     */








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












|










|



|







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
    }
    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 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(void *))
{
    ThreadSpecificData *tsdPtr;
    fd_set readableMask, writableMask, exceptionalMask;
    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
	 */

	if (receivePipe >= numFdBits) {
	    numFdBits = receivePipe + 1;
	}
	FD_SET(receivePipe, &readableMask);






	if (select(numFdBits, &readableMask, &writableMask, &exceptionalMask,
		timePtr) == -1) {












	    /*
	     * Try again immediately on an error.
	     */

	    continue;
	}








>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>







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
	 */

	if (receivePipe >= numFdBits) {
	    numFdBits = receivePipe + 1;
	}
	FD_SET(receivePipe, &readableMask);

	/*
	 * Signals are unblocked only during select().
	 */

	pthread_sigmask(SIG_SETMASK, &notifierSigMask, NULL);
	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
		 * 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;
	    }





	}
    }
    pthread_exit(0);
}

#ifdef HAVE_PTHREAD_ATFORK
/*







>
>
>
>
>







2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
		 * 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

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 defined(USE_OS_UNFAIR_LOCK)
    tsdPtr->tsdLock = OS_UNFAIR_LOCK_INIT;


#else
       UNLOCK_NOTIFIER_TSD;
       UNLOCK_NOTIFIER;
       UNLOCK_NOTIFIER_INIT;
#endif



    if (tsdPtr->runLoop) {
	tsdPtr->runLoop = NULL;
	if (!noCFafterFork) {
	    CFRunLoopSourceInvalidate(tsdPtr->runLoopSource);
	    CFRelease(tsdPtr->runLoopSource);
	    if (tsdPtr->runLoopTimer) {
		CFRunLoopTimerInvalidate(tsdPtr->runLoopTimer);







|
|
|



|
>
>

|
|
|

>
>
>







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

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 defined(USE_OS_UNFAIR_LOCK)
    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;
#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
	 * executed in the main thread of the parent, otherwise
	 * Tcl_AlertNotifier may break in the child.
	 */

	if (!noCFafterFork) {
	    Tcl_InitNotifier();
	}






    }
}
#endif /* HAVE_PTHREAD_ATFORK */

#else /* HAVE_COREFOUNDATION */

void
TclMacOSXNotifierAddRunLoopMode(
    const void *runLoopMode)
{
    Tcl_Panic("TclMacOSXNotifierAddRunLoopMode: "
	    "Tcl not built with CoreFoundation support");
}

#endif /* HAVE_COREFOUNDATION */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>
>
>







|


|












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
	 * 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
Tcl_MacOSXNotifierAddRunLoopMode(
    const void *runLoopMode)
{
    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 binary -encoding utf-8 -buffersize $bufSize -buffering full
  fconfigure $wch -translation binary -encoding utf-8 -buffersize $bufSize -buffering full

  exec [info nameofexecutable] -- $bufSize >@$wch << {
    set bufSize [lindex $::argv end]
    fconfigure stdout -translation binary -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
#!/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)
#
# 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]]} {











|







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 © 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
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 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







|







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 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
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}}



    # Scan : test rotate of GC objects (format is dynamic, so tcl-obj removed with last reference)

    {set i 0; time { clock scan "[incr i] - 25.11.2015" -format "$i - %d.%m.%Y" -base 0 -gmt 1 } 50}
    # Scan : test reusability of GC objects (format is dynamic, so tcl-obj removed with last reference)

    {set i 50; time { clock scan "[incr i -1] - 25.11.2015" -format "$i - %d.%m.%Y" -base 0 -gmt 1 } 50}


  }
}

proc test-ensemble-perf {{reptime 1000}} {
  _test_run $reptime {
    # Clock clicks (ensemble)
    {clock clicks}








>
>

>
|

>
|
>
>







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}
    {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}
    {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/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
#!/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 {{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

  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
# ------------------------------------------------------------------------
#
# 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)
#
# 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:

# 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
}












|






|







1
2
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 © 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 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
}

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
#!/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)
#
# See the file "license.terms" for information on usage and redistribution
# of this file.
#


if {![namespace exists ::tclTestPerf]} {











|







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 © 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
# 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.
#
# 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::*






|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 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 © 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::*

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
# 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
#
# 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]} {






|
|





<







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 © 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 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
# 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.
#
# 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 x




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]} {
	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-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 ""






|
|
|








>

>

>
>















|




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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 © 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} {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
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]} {
	    set j [lindex $var $i]
	    if {$j ne "item $i"} {
		return "element $i should have been \"item $i\", was \"$j\""
	    }
	}
	return ok
    }







|







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} {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
    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
    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
    proc foo {args} {append ::result $args}
    lappend myvar a
    return $::result
} -result {myvar {} r}
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
    proc foo {args} {append ::result $args}
    lappend myvar(b) a
    return $::result
} -result {myvar b r}
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
    proc foo {args} {append ::result $args}
    lappend myvar(b) a
    return $::result
} -result {myvar b r}
test append-7.5 {append var does not trigger read trace} -setup {
    unset -nocomplain myvar
    unset -nocomplain ::result
} -body {
    trace variable myvar r foo
    proc foo {args} {append ::result $args}
    append myvar a
    info exists ::result
} -result {0}

# THERE ARE NO append-8.* TESTS








|












|



|






|



|





|



|




|







217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
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 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 add variable myvar read foo
    proc foo {args} {append ::result $args}
    lappend myvar a
    return $::result
} -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 add variable myvar read foo
    proc foo {args} {append ::result $args}
    lappend myvar(b) a
    return $::result
} -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 add variable myvar read foo
    proc foo {args} {append ::result $args}
    lappend myvar(b) a
    return $::result
} -result {myvar b read}
test append-7.5 {append var does not trigger read trace} -setup {
    unset -nocomplain myvar
    unset -nocomplain ::result
} -body {
    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
# 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.
#
# 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::*






|
|
|







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 © 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
    }
    foo
} abcd

test appendComp-2.1 {long appends} {
    proc foo {} {
	set x ""
	for {set i 0} {$i < 1000} {set i [expr $i+1]} {
	    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}







|







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} {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
		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]} {
	lappend x "item $i"
    }
    check $x 300
} -cleanup {
    unset -nocomplain x
    catch {rename check ""}
} -result ok







|







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} {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

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
	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
	proc foo {args} {append ::result $args}
	lappend myvar a
	return $::result
    }
    bar
} -result {myvar {} r} -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
	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
	proc foo {args} {append ::result $args}
	lappend myvar(b) a
	return $::result
    }
    bar
} -result {myvar b r} -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
	proc foo {args} {append ::result $args}
	lappend myvar(b) a b
	return $::result
    }
    bar
} -result {myvar b r}
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
	proc foo {args} {append ::result $args}
	lappend myvar(b) a
	return $::result
    }
    bar
} -result {myvar b r} -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
	proc foo {args} {append ::result $args}
	lappend ::myvar(b) a
	return $::result
    }
    bar
} -result {::myvar b r} -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
	proc foo {args} {append ::result $args}
	lappend ::myvar(b) a b
	return $::result
    }
    bar
} -result {::myvar b r}
test appendComp-7.9 {append var does not trigger read trace} -setup {
    unset -nocomplain ::result
} -body {
    proc bar {} {
	trace variable myvar r foo
	proc foo {args} {append ::result $args}
	append myvar a
	info exists ::result
    }
    bar
} -result {0}








|














|





|





|












|





|






|





|





|





|





|





|





|





|




|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 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 add variable myvar read foo
	proc foo {args} {append ::result $args}
	lappend myvar a
	return $::result
    }
    bar
} -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 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 add variable myvar read foo
	proc foo {args} {append ::result $args}
	lappend myvar(b) a
	return $::result
    }
    bar
} -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 add variable myvar read foo
	proc foo {args} {append ::result $args}
	lappend myvar(b) a b
	return $::result
    }
    bar
} -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 add variable myvar read foo
	proc foo {args} {append ::result $args}
	lappend myvar(b) a
	return $::result
    }
    bar
} -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 add variable ::myvar read foo
	proc foo {args} {append ::result $args}
	lappend ::myvar(b) a
	return $::result
    }
    bar
} -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 add variable ::myvar read foo
	proc foo {args} {append ::result $args}
	lappend ::myvar(b) a b
	return $::result
    }
    bar
} -result {::myvar b read}
test appendComp-7.9 {append var does not trigger read trace} -setup {
    unset -nocomplain ::result
} -body {
    proc bar {} {
	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
# 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.

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







|







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 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
# 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
#
# 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 {[info commands ::apply] eq {}} {
    return
}

testConstraint memory [llength [info commands memory]]



# 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 ...?"}







|
|
|
|








>
>






>
>







1
2
3
4
5
6
7
8
9
10
11
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 © 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
	set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    rename getbytes {}
    unset -nocomplain end i x tmp leakedBytes
} -result 0








# Tests for the avoidance of recompilation

# cleanup

namespace delete testApply








>
>
>
>
>
>
>







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
# assemble.test --
#
#	Test suite for the 'tcl::unsupported::assemble' command
#
# Copyright (c) 2010 by Ozgur Dogan Ugurlu.
# Copyright (c) 2010 by 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





|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
# assemble.test --
#
#	Test suite for the 'tcl::unsupported::assemble' command
#
# 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
	    assemble
	}
	x
    }
    -returnCodes error
    -match glob
    -result {wrong # args:*}

}
test assemble-3.2 {wrong # args, compiled path} {
    -body {
	proc x {} {
	    assemble too many
	}
	x







>







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
	    assemble {
		[x]
	    }
	}
	list [catch {x} result] $result $::errorCode
    }
    -result {1 {assembly code may not contain substitutions} {TCL ASSEM NOSUBST}}

}
test assemble-5.4 {backslash substitution} {
    -body {
	proc x {} {
	    assemble {
		p\x75sh\
		    hello\ world







>







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
618
619
620
621
622
623
624

625
626
627
628
629
630
631
	    assemble {
		push {2 1}; push i; load l; lsetList
	    }
	}
	x
    }
    -result {{a b} {c d} {e i} {g h}}

}
test assemble-7.25 {lshift} {
    -body {
	assemble {push 16; push 4; lshift}
    }
    -result 256
}







>







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
}
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
	}
	catch {x 1}
	set errorInfo
    }
    -match glob
    -result {inconsistent stack depths on two execution paths
    ("assemble" body, line 10)*}

}
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)*}

}
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)*}

}

test assemble-50.1 {Ulam's 3n+1 problem, TAL implementation} {
    -body {
	proc ulam {n} {
	    assemble {
		load n;		# max







>


















>



















>







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
	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}

}

test assemble-51.1 {memory leak testing} memory {
    leaktest {
	apply {{} {assemble {push hello}}}
    }
} 0







>







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
	    pop
	}
    }}
} {};				# must not crash

rename fillTables {}
rename assemble {}





::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:







>
>
>
>








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
# 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.
#
# 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]]

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






|
|
|










|







1
2
3
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 © 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 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
# 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.
#
# 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]]


testConstraint testasync [llength [info commands testasync]]
testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

proc async1 {result code} {
    global aresult acode
    set aresult $result
    set acode $code
    return "new result"
}






|
|
|










|

>

|







1
2
3
4
5
6
7
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 © 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 tcl::test [info patchlevel]]

testConstraint thread [expr {0 == [catch {package require Thread 2.7-}]}]
testConstraint testasync [llength [info commands testasync]]
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

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
} -setup {
    set hm [testasync create async3]
    proc nothing {} {
	# empty proc
    }
} -body {
    apply {{handle} {







|







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 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
} -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
} -setup {
    set hm [testasync create async3]
} -body {
    apply {{handle} {
	global aresult
	set aresult {Async event not delivered}
	testasync marklater $handle







|







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 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
} -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
} -setup {
    set hm [testasync create async3]
} -body {
    apply [list {handle} [concat {
	global aresult
	set aresult {Async event not delivered}
	testasync marklater $handle







|







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 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
# 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.
#
# 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::*





|
|







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 © 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
#           proc another {args} { ... }
#       }
#   }
#
# Note that procedures and itcl class definitions can be nested inside of
# namespaces.
#
# Copyright (c) 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]}

#
# 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"}







|







|
|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#           proc another {args} { ... }
#       }
#   }
#
# Note that procedures and itcl class definitions can be nested inside of
# namespaces.
#
# 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}]}

#
# 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"}
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
    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]}"
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







|







121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
    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 -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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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"
    }
    auto_mkindex . autoMkindex.tcl
    namespace eval tcl_autoMkindex_tmp {
        set dir "."
        variable auto_index
        source tclIndex
        set ::result ""







|







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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 -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 ""
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
    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"
    }
    auto_mkindex . autoMkindex.tcl
    namespace eval tcl_autoMkindex_tmp {
        set dir "."
        variable auto_index
        source tclIndex
        set ::result ""







|







212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
    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 -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 ""
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]]}}
removeFile ensemblecommands.tcl

test autoMkindex-4.1 {platform independent source commands} -setup {
    file delete tclIndex
    makeDirectory pkg
    makeFile {
	package provide football 1.0







|







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 -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
    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]]}}

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 \







|







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 -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
    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]]}
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 {}







|







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 -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
# 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.
#
# 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]]

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}











|
|










|







1
2
3
4
5
6
7
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 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 © 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 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}
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
    proc n::p {} {}
} -cleanup {
    namespace delete n
    rename deleter {}
}


test basic-16.1 {TclInvokeStringCommand} {emptyTest} {
} {}

test basic-17.1 {TclInvokeObjCommand} {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 {} {







|


|







238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
    proc n::p {} {}
} -cleanup {
    namespace delete n
    rename deleter {}
}


test basic-16.1 {InvokeStringCommand} {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 {} {
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
    list [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
} {{#} ::#}

test basic-21.1 {Tcl_GetCommandName} {emptyTest} {
} {}

test basic-22.1 {Tcl_GetCommandFullName} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}







|







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
    list [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 \#]
    return [testcmdtoken name $x]
} {{#} ::#}

test basic-21.1 {Tcl_GetCommandName} {emptyTest} {
} {}

test basic-22.1 {Tcl_GetCommandFullName} {
    catch {namespace delete {*}[namespace children :: test_ns_*]}
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 {
    interp alias {} run {} testevalex
    set constraints testevalex
} else {
    interp alias {} run {} if 1
    set constraints {}
}








|







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} {
    interp alias {} run {} testevalex
    set constraints testevalex
} else {
    interp alias {} run {} if 1
    set constraints {}
}

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
# 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.
#
# 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 bigEndian [expr {$tcl_platform(byteOrder) eq "bigEndian"}]
testConstraint littleEndian [expr {$tcl_platform(byteOrder) eq "littleEndian"}]
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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 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
51
52
53
54
55
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 © 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    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
    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
test binary-4.5 {Tcl_BinaryObjCmd: format} {
    binary format B8 01001101
} \x4d
test binary-4.6 {Tcl_BinaryObjCmd: format} {
    binary format A2X2B9 oo 01001101
} \x4d\x00
test binary-4.7 {Tcl_BinaryObjCmd: format} {
    binary format B9 010011011010
} \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}








|


|


|


|







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
test binary-4.5 {Tcl_BinaryObjCmd: format} {
    binary format B8 01001101
} \x4D
test binary-4.6 {Tcl_BinaryObjCmd: format} {
    binary format A2X2B9 oo 01001101
} \x4D\x00
test binary-4.7 {Tcl_BinaryObjCmd: format} {
    binary format B9 010011011010
} \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
    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
test binary-5.6 {Tcl_BinaryObjCmd: format} {
    binary format A2X2b9 oo 01001101
} \xb2\x00
test binary-5.7 {Tcl_BinaryObjCmd: format} {
    binary format b9 010011011010
} \xb2\x01
test binary-5.8 {Tcl_BinaryObjCmd: format} {
    binary format b17 1
} \x01\00\00
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
test binary-6.5 {Tcl_BinaryObjCmd: format} {
    binary format h* baadf00d
} \xab\xda\x0f\xd0
test binary-6.6 {Tcl_BinaryObjCmd: format} {
    binary format h4 c410
} \x4c\x01
test binary-6.7 {Tcl_BinaryObjCmd: format} {
    binary format h6 c4102
} \x4c\x01\x02
test binary-6.8 {Tcl_BinaryObjCmd: format} {
    binary format h5 c41020304
} \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 {







|


|


|


|


















|


|


|


|


|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
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
test binary-5.6 {Tcl_BinaryObjCmd: format} {
    binary format A2X2b9 oo 01001101
} \xB2\x00
test binary-5.7 {Tcl_BinaryObjCmd: format} {
    binary format b9 010011011010
} \xB2\x01
test binary-5.8 {Tcl_BinaryObjCmd: format} {
    binary format b17 1
} \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
test binary-6.5 {Tcl_BinaryObjCmd: format} {
    binary format h* baadf00d
} \xAB\xDA\x0F\xD0
test binary-6.6 {Tcl_BinaryObjCmd: format} {
    binary format h4 c410
} \x4C\x01
test binary-6.7 {Tcl_BinaryObjCmd: format} {
    binary format h6 c4102
} \x4C\x01\x02
test binary-6.8 {Tcl_BinaryObjCmd: format} {
    binary format h5 c41020304
} \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
    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
test binary-7.5 {Tcl_BinaryObjCmd: format} {
    binary format H* baadf00d
} \xba\xad\xf0\x0d
test binary-7.6 {Tcl_BinaryObjCmd: format} {
    binary format H4 c410
} \xc4\x10
test binary-7.7 {Tcl_BinaryObjCmd: format} {
    binary format H6 c4102
} \xc4\x10\x20
test binary-7.8 {Tcl_BinaryObjCmd: format} {
    binary format H5 c41023304
} \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 {







|


|


|


|


|







255
256
257
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
test binary-7.5 {Tcl_BinaryObjCmd: format} {
    binary format H* baadf00d
} \xBA\xAD\xF0\x0D
test binary-7.6 {Tcl_BinaryObjCmd: format} {
    binary format H4 c410
} \xC4\x10
test binary-7.7 {Tcl_BinaryObjCmd: format} {
    binary format H6 c4102
} \xC4\x10\x20
test binary-7.8 {Tcl_BinaryObjCmd: format} {
    binary format H5 c41023304
} \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 {
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
    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
test binary-13.5 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f 1.6
} \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
test binary-13.7 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f* {1.6 3.4}
} \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
test binary-13.9 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f2 {1.6 3.4}
} \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
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
test binary-13.12 {Tcl_BinaryObjCmd: float overflow} bigEndian {
    binary format f -3.402825e+38
} \xff\x7f\xff\xff
test binary-13.13 {Tcl_BinaryObjCmd: float overflow} littleEndian {
    binary format f -3.402825e+38
} \xff\xff\x7f\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\""
test binary-13.18 {Tcl_BinaryObjCmd: format} bigEndian {
    set a {1.6 3.4}
    binary format f1 $a
} \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













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
test binary-14.5 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format d 1.6
} \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
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
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
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
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
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
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\""
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
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
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"







|


|


|


|


|


|


|


|


|


|
















|



|
>
>
>
>
>
>
>
>
>
>
>
>












|


|


|


|


|


|


|


|










|



|







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
    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
test binary-13.5 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f 1.6
} \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
test binary-13.7 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f* {1.6 3.4}
} \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
test binary-13.9 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format f2 {1.6 3.4}
} \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
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
test binary-13.12 {Tcl_BinaryObjCmd: float overflow} bigEndian {
    binary format f -3.402825e+38
} \xFF\x80\x00\x00
test binary-13.13 {Tcl_BinaryObjCmd: float overflow} littleEndian {
    binary format f -3.402825e+38
} \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\""
test binary-13.18 {Tcl_BinaryObjCmd: format} bigEndian {
    set a {1.6 3.4}
    binary format f1 $a
} \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
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
test binary-14.5 {Tcl_BinaryObjCmd: format} littleEndian {
    binary format d 1.6
} \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
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
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
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
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
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
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\""
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
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
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
    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-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}







|
>
>
>
>
>
>
>
>
>







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
} -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
} {1 253a}
test binary-24.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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







|



|











|







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
} {1 253a}
test binary-24.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} -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
} {1 52a3}
test binary-25.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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







|



|











|







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
} {1 52a3}
test binary-25.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {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
} {1 {82 -93}}
test binary-26.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 82}
test binary-26.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 {82 -93}}
test binary-26.7 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 {82 163}}
test binary-26.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {1 {-23726 21587}}
test binary-27.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 -23726}
test binary-27.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {2 {-23726 21587} 5}
test binary-27.10 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {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
} {1 {21155 21332}}
test binary-28.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 21155}
test binary-28.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {2 {21155 21332} 5}
test binary-28.10 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {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
} {1 1414767442}
test binary-29.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {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
} {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
} {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
} {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
} {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
} {1 1386435412}
test binary-30.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {1 1.600000023841858}
test binary-31.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {1 1.600000023841858}
test binary-31.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {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
} {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
} {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)
} -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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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)
} -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
} {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
} {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}







|



|



|



|



|



|




















|



|



|



















|



|



|



|



|
















|



|





|





|







|



|



|



|



|
















|



|



|







|



|



|



|



|
















|



|



|











|



|



|



|



|
















|



|



|











|



|



|



|



|



|



|



|



|



|










|





|





|







|



|



|



|



|



|



|



|



|



|










|





|





|







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
} {1 {82 -93}}
test binary-26.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 82}
test binary-26.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 {82 -93}}
test binary-26.7 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 {82 163}}
test binary-26.12 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {1 {-23726 21587}}
test binary-27.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 -23726}
test binary-27.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {2 {-23726 21587} 5}
test binary-27.10 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {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
} {1 {21155 21332}}
test binary-28.3 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {1 21155}
test binary-28.5 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {2 {21155 21332} 5}
test binary-28.10 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {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
} {1 1414767442}
test binary-29.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {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
} {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
} {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
} {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
} {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
} {1 1386435412}
test binary-30.4 {Tcl_BinaryObjCmd: scan} {
    unset -nocomplain 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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {1 1.600000023841858}
test binary-31.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {1 1.600000023841858}
test binary-31.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {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
} {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
} {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)
} -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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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)
} -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
} {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
} {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
    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
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
test binary-38.7 {FormatNumber: word alignment} bigEndian {
    set x [binary format c1f1 1 1.6]
} \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

test binary-39.1 {ScanNumber: sign extension} {
    unset -nocomplain 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
} {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
} -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
} -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}







|


|


|


|



|



















|




















|



|







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
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
test binary-38.7 {FormatNumber: word alignment} bigEndian {
    set x [binary format c1f1 1 1.6]
} \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

test binary-39.1 {ScanNumber: sign extension} {
    unset -nocomplain 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
} {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
} -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
} -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
    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
} -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
} -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
} -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
} -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







|




|




|




|







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
} -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
} -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
} -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
} -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
} {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
test binary-46.2 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    list [binary scan [binary format a* \u20ac\u20bd] 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 {}"
test binary-46.4 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    set x [encoding convertto iso8859-15 \u20ac]
    set y [binary format a* $x]
    list $x $y
} "\u00a4 \u00a4"
test binary-46.5 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    set x [binary scan \u00a4 a* y]
    list $x $y [encoding convertfrom iso8859-15 $y]
} "1 \u00a4 \u20ac"

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







|
|

|





|
|

|


|

|

|







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* 
} \xAC
test binary-46.2 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    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* €₽] 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 ]
    set y [binary format a* $x]
    list $x $y
} "\xA4 \xA4"
test binary-46.5 {Tcl_BinaryObjCmd: handling of non-ISO8859-1 chars} {
    set x [binary scan \xA4 a* y]
    list $x $y [encoding convertfrom iso8859-15 $y]
} "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
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
    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
test binary-51.5 {Tcl_BinaryObjCmd: format} {} {
    binary format q 1.6
} \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
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
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
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
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
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
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\""
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
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

# 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
test binary-53.5 {Tcl_BinaryObjCmd: format} {} {
    binary format r 1.6
} \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
test binary-53.7 {Tcl_BinaryObjCmd: format} {} {
    binary format r* {1.6 3.4}
} \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
test binary-53.9 {Tcl_BinaryObjCmd: format} {} {
    binary format r2 {1.6 3.4}
} \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
test binary-53.11 {Tcl_BinaryObjCmd: format} {} {
    binary format r2 {1.6 3.4 5.6}
} \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
test binary-53.13 {Tcl_BinaryObjCmd: float overflow} {} {
    binary format r -3.402825e+38
} \xff\xff\x7f\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\""
test binary-53.18 {Tcl_BinaryObjCmd: format} {} {
    set a {1.6 3.4}
    binary format R1 $a
} \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


































# 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
} {1 {-23726 21587}}
test binary-54.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain 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
} {1 -23726}
test binary-54.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain 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
} {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
} {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
} {1 {21155 21332}}
test binary-55.3 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {1 21155}
test binary-55.5 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {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
} {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
} {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
} {1 1414767442}
test binary-56.4 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain 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
} {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
} {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
} {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
} {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
} {1 1386435412}
test binary-57.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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)
} -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
} {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
} {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
} {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
} {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
} {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
} {1 1.600000023841858}
test binary-59.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {1 1.600000023841858}
test binary-59.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {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
} {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
} {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)
} -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
} {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
} {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:]]+\))?}







|


|


|


|


|


|


|


|










|



|













|


|


|


|


|


|


|


|


|


|
















|



|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|



|



|



|



|
















|




















|



|



|



|



|
















|




















|



|



|



|



|
















|




















|



|



|



|



|
















|




















|



|



|



|



|



|



|



|



|



|










|





|





|








|



|



|



|



|



|



|



|



|



|










|





|





|







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
test binary-51.5 {Tcl_BinaryObjCmd: format} {} {
    binary format q 1.6
} \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
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
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
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
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
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
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\""
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
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

# 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
test binary-53.5 {Tcl_BinaryObjCmd: format} {} {
    binary format r 1.6
} \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
test binary-53.7 {Tcl_BinaryObjCmd: format} {} {
    binary format r* {1.6 3.4}
} \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
test binary-53.9 {Tcl_BinaryObjCmd: format} {} {
    binary format r2 {1.6 3.4}
} \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
test binary-53.11 {Tcl_BinaryObjCmd: format} {} {
    binary format r2 {1.6 3.4 5.6}
} \xCD\xCC\xCC\x3F\x9A\x99\x59\x40
test binary-53.12 {Tcl_BinaryObjCmd: float overflow} {} {
    binary format R -3.402825e+38
} \xFF\x80\x00\x00
test binary-53.13 {Tcl_BinaryObjCmd: float overflow} {} {
    binary format r -3.402825e+38
} \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\""
test binary-53.18 {Tcl_BinaryObjCmd: format} {} {
    set a {1.6 3.4}
    binary format R1 $a
} \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
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
} {1 {-23726 21587}}
test binary-54.3 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain 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
} {1 -23726}
test binary-54.5 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain 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
} {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
} {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
} {1 {21155 21332}}
test binary-55.3 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {1 21155}
test binary-55.5 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {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
} {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
} {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
} {1 1414767442}
test binary-56.4 {Tcl_BinaryObjCmd: scan} littleEndian {
    unset -nocomplain 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
} {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
} {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
} {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
} {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
} {1 1386435412}
test binary-57.4 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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
} {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)
} -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
} {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
} {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
} {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
} {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
} {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
} {1 1.600000023841858}
test binary-59.6 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {1 1.600000023841858}
test binary-59.8 {Tcl_BinaryObjCmd: scan} bigEndian {
    unset -nocomplain 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
} {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
} {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
} {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)
} -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
} {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
} {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
    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
    set d
} Inf
test binary-62.6 {infinity} ieeeFloatingPoint {
    binary scan [binary format w 0xfff0000000000000] q 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}]
} 0x7ff0000000000000
test binary-63.2 {NaN} ieeeFloatingPoint {
    binary scan [binary format q -NaN] w w
    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}]
} 0x7ff3123456789abc
test binary-63.4 {NaN} ieeeFloatingPoint {
    binary scan [binary format q {NaN( 3123456789aBc)}] w w
    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 {







|



|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|



|



|



|







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
    set d
} Inf
test binary-62.6 {infinity} ieeeFloatingPoint {
    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}]
} 0x7ff0000000000000
test binary-63.2 {NaN} ieeeFloatingPoint {
    binary scan [binary format q -NaN] w w
    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}]
} 0x7ff3123456789abc
test binary-63.4 {NaN} ieeeFloatingPoint {
    binary scan [binary format q {NaN( 3123456789aBc)}] w w
    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
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
} -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"
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
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 \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 "\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
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
} -result {AAECAwQAAQID}
test binary-72.6 {binary encode base64} -body {
    binary encode base64 \0
} -result {AA==}
test binary-72.7 {binary encode base64} -body {
    binary encode base64 \0\0
} -result {AAA=}
test binary-72.8 {binary encode base64} -body {
    binary encode base64 \0\0\0
} -result {AAAA}
test binary-72.9 {binary encode base64} -body {
    binary encode base64 \0\0\0\0
} -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}







|


|


|


|


|







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 \x00\x01\x02\x03\x04\x00\x01\x02\x03
} -result {AAECAwQAAQID}
test binary-72.6 {binary encode base64} -body {
    binary encode base64 \x00
} -result {AA==}
test binary-72.7 {binary encode base64} -body {
    binary encode base64 \x00\x00
} -result {AAA=}
test binary-72.8 {binary encode base64} -body {
    binary encode base64 \x00\x00\x00
} -result {AAAA}
test binary-72.9 {binary encode base64} -body {
    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
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]
} 5







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"
test binary-73.6 {binary decode base64} -body {
    binary decode base64 AA==
} -result "\0"
test binary-73.7 {binary decode base64} -body {
    binary decode base64 AAA=
} -result "\0\0"
test binary-73.8 {binary decode base64} -body {
    binary decode base64 AAAA
} -result "\0\0\0"
test binary-73.9 {binary decode base64} -body {
    binary decode base64 AAAAAA==
} -result "\0\0\0\0"
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







|

>
>
>
>
>
>















|


|


|


|


|







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]
} 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 "\x00\x01\x02\x03\x04\x00\x01\x02\x03"
test binary-73.6 {binary decode base64} -body {
    binary decode base64 AA==
} -result "\x00"
test binary-73.7 {binary decode base64} -body {
    binary decode base64 AAA=
} -result "\x00\x00"
test binary-73.8 {binary decode base64} -body {
    binary decode base64 AAAA
} -result "\x00\x00\x00"
test binary-73.9 {binary decode base64} -body {
    binary decode base64 AAAAAA==
} -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
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
} -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
} -result "\"```
"
test binary-74.8 {binary encode uuencode} -body {
    binary encode uuencode \0\0\0
} -result {#````
}
test binary-74.9 {binary encode uuencode} -body {
    binary encode uuencode \0\0\0\0
} -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







|






|



|



|







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 \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 \x00\x00
} -result "\"```
"
test binary-74.8 {binary encode uuencode} -body {
    binary encode uuencode \x00\x00\x00
} -result {#````
}
test binary-74.9 {binary encode uuencode} -body {
    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
    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"
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 {







|







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 "\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
} [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 {}


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



} A







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 {
    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 {
    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 {
    testbytestring [testbytestring "\xC0\x80\xA0\xA0\xA0\xF0\x9F\x98\x81"]
} -result "expected byte sequence but character 4 was '\U01F601' (U+01F601)"






# ----------------------------------------------------------------------
# cleanup

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|








|
>
>
>
|
>
>
>

>
>
>
>
>
>

|
|
|
|

|
|

|
|


>
>
>
>
>










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 * -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} -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 {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 '' (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 '' (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
# 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
#
# 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::*
}




#
# 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 {




|








>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 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 © 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 {
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
} -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 ...?\""
test chan-4.2 {chan command: [Bug 800753]} -body {
    chan configure stdout -eofchar \u0100
} -returnCodes error -match glob -result {bad value*}
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 [list \x27 {}]
} -returnCodes ok -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:*}
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 {} {}]}

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







|
|

|
|
|

|


|


|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
} -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 ...?\""
test chan-4.2 {chan command: [Bug 800753]} -body {
    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 \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 {}]
} -result {}
test chan-4.5 {chan command: check valid inValue, invalid outValue} -body {
    chan configure stdout -eofchar [list \x27 \x80]
} -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 error -result {bad value for -eofchar: must be non-NUL ASCII character} -cleanup {chan configure stdout -eofchar {}}

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

Changes to tests/chanio.test.

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.
#
# 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::*








|
|
|







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 © 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
    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 tcltests

    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 knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]
    testConstraint notOSX [expr {$::tcl_platform(os) ne "Darwin"}]




    # 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]
    chan configure $f -eofchar {} -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 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







|
|

|







>
|

>
>
>










|


















|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    variable n
    variable v
    variable msg
    variable expected

    catch {
	::tcltest::loadTestedCommands
	package require -exact tcl::test [info patchlevel]
	set ::tcltestlib [info loaded {} Tcltest]
    }
    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 {
	$::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 $::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
    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 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
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 close $f
    contents $path(test1)
} "a\x4d\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 close $f
    contents $path(test1)
} "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"
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







|


|



|


|












|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
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\x4D\x00"
    chan close $f
    contents $path(test1)
} 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\x00"
    chan close $f
    contents $path(test1)
} "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"
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257


258
259
260
261
262
263
264
265
266



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284


285
286
287
288
289
290
291
292
293
294
295
296
297


298
299
300
301
302
303
304
305
306


307
308
309
310
311
312
313
314
    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} {
    # 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 puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]


} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.5 {WriteChars: saved != 0} {
    # 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 puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]



    chan close $f
    lappend x [contents $path(test1)]
} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-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
    # 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.
    set f [open $path(test1) w]
    chan configure $f -encoding shiftjis -buffersize 16
    chan puts -nonewline $f "12345678901234\uff21\uff22"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]


} [list "12345678901234\x82\x60" "12345678901234\x82\x60\x82\x61"]
test chan-io-3.7 {WriteChars: (bufPtr->nextAdded > bufPtr->length)} {
    # 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 puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]


} [list "!)!)!)!)!)!)!)!)!" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test chan-io-3.8 {WriteChars: reset sawLF after each buffer} {
    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)]


} [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)]]







|


|




>
>
|
|




|


>
>
>
|
<
|
|




|


|


|



>
>
|
|






|




>
>
|
|







>
>
|







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276

277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
    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} -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 -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}
} -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 -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}

} -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  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  plus the all of ) appended.
    set f [open $path(test1) w]
    chan configure $f -encoding shiftjis -buffersize 16
    chan puts -nonewline $f 12345678901234AB
    set x [list [contents $path(test1)]]
    chan close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {chan close $f}
} -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 -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}
} -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}
} -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)]]
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
    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 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 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"]
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







|










|






|







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
    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\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 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 "一丁"]
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
    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 close $f
    set f [open $path(test1)]
    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 close $f
    set f [open $path(test1)]
    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]







|


|






|


|







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
    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 close $f
    set f [open $path(test1)]
    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\x1Abat"
    chan close $f
    set f [open $path(test1)]
    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
    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"
    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"
    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 ""







|

















|







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
    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"
    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"
    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
    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"
    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]







|







928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
    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"
    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
} -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 close $f
    set f [open $path(test1)]
    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]







|


|







994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
} -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 close $f
    set f [open $path(test1)]
    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
} -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 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"]
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"







|






|







1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
} -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 "thereok\nmore 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 "thereok" 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
    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 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"
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 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 close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis
    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 ""]
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 -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 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]

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







|






|




|












|


|





|





|












|







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
    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 "123456789012301234\nend"
    chan close $f
    set f [open $path(test1)]
    chan configure $f -encoding shiftjis -buffersize 16
    chan gets $f
} -cleanup {
    chan close $f
} -result "123456789012301234"
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 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 close $f
    set f [open $path(test1)]
    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 16 "123456789012301\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 -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 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 "12345678901230123" 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
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
} -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"
    lappend x [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result {15 abcdefghijklmno 1 -1 {}}

test chan-io-9.1 {CommonGetsCleanup} emptyTest {
} {}







|







1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
} -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
    lappend x [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result {15 abcdefghijklmno 1 -1 {}}

test chan-io-9.1 {CommonGetsCleanup} emptyTest {
} {}
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
    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"
    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]
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"
    } 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
	}







|






|





|
|
|







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
    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
    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  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
    } 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
    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 {}"

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)]







|







1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
    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  {} 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
    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')
    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')
    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







|











|







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
    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 != '\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 != '\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
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
    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}]
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}}
test chan-io-20.5 {Tcl_CreateChannel: install channel in empty slot} -setup {
    set path(stdout) [makeFile {} stdout]
} -constraints {stdio knownMsvcBug} -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







|





|


|







1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
    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 {{} {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}}
test chan-io-20.5 {Tcl_CreateChannel: install channel in empty slot} -setup {
    set path(stdout) [makeFile {} stdout]
} -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
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
    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 {
    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} {







|







2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
    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 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
    }
    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]
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]
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







|
















|







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
    }
    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}]
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}]
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
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 close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    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 puts $f hello\nthere\nand\rhere
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    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
    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
    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]







|


|












|



|

















|




















|







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
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 close $f
    set f [open $path(test1) r]
    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 -translation lf -eofchar \x1A
    chan puts $f hello\nthere\nand\rhere
    chan close $f
    set f [open $path(test1) r]
    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 -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 -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]
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
    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"
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 puts $f [format "abc\ndef\n%cghi\nqrs" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation cr -eofchar {}
    set x [chan gets $f]
    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 puts $f [format "abc\ndef\n%cghi\nqrs" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf -eofchar {}
    set x [chan gets $f]
    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
    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
    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
    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
    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
    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
    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.







|











|

















|














|













|













|













|













|













|







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
    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"
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 puts $f [format "abc\ndef\n%cghi\nqrs" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation cr -eofchar {}
    set x [chan gets $f]
    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 puts $f [format "abc\ndef\n%cghi\nqrs" 26]
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -translation crlf -eofchar {}
    set x [chan gets $f]
    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
    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
    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
    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
    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
    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
    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
    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.
#
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







|







3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
    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 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
    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
    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 puts $f hello\nthere\nand\rhere
    chan close $f
    set f [open $path(test1) r]
    chan configure $f -eofchar \x1a -translation auto
    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
    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
    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







|















|



|



















<
|

















|







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
    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 -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 -translation lf -eofchar \x1A
    chan puts $f hello\nthere\nand\rhere
    chan close $f
    set f [open $path(test1) r]
    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 -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 -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
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
    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"
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 puts $f [format "abc\ndef\n%cqrs\ntuv" 26]







|







3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
    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"
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 puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
    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"
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 puts $f [format "abc\ndef\n%cqrs\ntuv" 26]







|







3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
    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"
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 puts $f [format "abc\ndef\n%cqrs\ntuv" 26]
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
    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"
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
    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
    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 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
    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 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
    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 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
    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 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
    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







|









|

















|

















|

















|

















|

















|







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
    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"
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
    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
    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 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
    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 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
    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 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
    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 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
    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
    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]
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]

# 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} {







|



















|







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
    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}]
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}]

# 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} {
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
    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 {
    set f [open $path(test3) w]
    chan configure $f -encoding binary
    lappend l [chan tell $f]
    chan puts -nonewline $f abcdef
    lappend l [chan tell $f]
    chan flush $f
    lappend l [chan tell $f]







|







4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
    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 extensive} -body {
    set f [open $path(test3) w]
    chan configure $f -encoding binary
    lappend l [chan tell $f]
    chan puts -nonewline $f abcdef
    lappend l [chan tell $f]
    chan flush $f
    lappend l [chan tell $f]
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
} -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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {9 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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {9 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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {9 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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {9 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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {11 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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {11 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 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
    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 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
    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 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
    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 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
    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 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
    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 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
    list $c [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -result {21 8 1}

# Test Tcl_InputBlocked








|




|



|




|




|



|




|




|



|




|




|



|




|




|



|




|




|



|









|













|













|













|













|













|







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
} -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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -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 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
    list $s [string length [chan read $f]] [chan eof $f]
} -cleanup {
    chan close $f
} -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 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
    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 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
    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 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
    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 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
    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 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
    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 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
    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
    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
    set var [chan read $chan 2]
    chan configure $chan -buffersize 32
    append var [chan read $chan]
    chan close $chan
} {}

# Test Tcl_SetChannelOption, Tcl_GetChannelOption







|







4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
    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 -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
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
    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 close $f
    set f [open $path(test1) r]
    chan configure $f -encoding utf-8
    chan read $f
} -cleanup {
    chan close $f
} -result \u7266
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 close $f
    set f [open $path(test1) r]
    chan configure $f -encoding utf-8
    chan read $f
} -cleanup {
    chan close $f
} -result \u7266
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 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
    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"
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







|






|





|






|













|

















|







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
    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 close $f
    set f [open $path(test1) r]
    chan configure $f -encoding utf-8
    chan read $f
} -cleanup {
    chan close $f
} -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 close $f
    set f [open $path(test1) r]
    chan configure $f -encoding utf-8
    chan read $f
} -cleanup {
    chan close $f
} -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 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
    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"
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
} -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 {
    set f1 [open $path(test1) w+]
    lappend l [chan configure $f1 -eofchar]
    chan configure $f1 -eofchar {ON GO}
    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 {
    file delete $path(test1)
    set l [list]
} -body {
    set f1 [open $path(test1) w+]
    chan configure $f1 -eofchar {ON GO}
    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 {

    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}
test chan-io-39.24 {Tcl_SetChannelOption, server socket is not readable or\
        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}

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]
    file stat $path(test3) stats
    set x [format "%#o" [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 {
    # 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}]]
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







|


|





|
|




|






|
>
|
|
>







|










|



















|
|

|









|



|
|







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
} -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 deprecated} -body {
    set f1 [open $path(test1) w+]
    lappend l [chan configure $f1 -eofchar]
    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 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 {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 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}
test chan-io-39.24 {Tcl_SetChannelOption, server socket is not readable or\
        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}

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 notWsl} -body {
    set f [open $path(test3) {WRONLY CREAT} 0o600]
    file stat $path(test3) stats
    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 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 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
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
    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_ ~

} -body {

    file exists [file join $::env(HOME) _test_]
} -cleanup {
    removeFile _test_ ~


} -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?"}
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?"}
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 event on a file
#

set path(foo) [makeFile {} foo]
set f [open $path(foo) w+]








|
|
>

>
|

<
>
>

<
<
<
<
<
<
<
<

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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 {verify no tilde substitution in open} -setup {
    set curdir [pwd]
    cd [temporaryDirectory]
} -body {
    close [open ~ w]
    list [file isfile ~]
} -cleanup {

    file delete ./~ ;# ./ because don't want to delete home in case of bugs!
    cd $curdir
} -result 1









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?"}
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?"}
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
    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"
    lappend result [string length [chan event $f readable]]
    chan event $f r "new scr\0ipt"
    lappend result [string length [chan event $f readable]]
    chan event $f r "yet ano\0ther"
    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 {}







|

|

|







5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
    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\x00ipt"
    lappend result [string length [chan event $f readable]]
    chan event $f r "new scr\x00ipt"
    lappend result [string length [chan event $f readable]]
    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 {}
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
    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 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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
    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 -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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
    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 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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
    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 -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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
    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 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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
    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 -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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
    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 -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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
    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 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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
    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 -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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
    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 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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
    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 -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
    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 event $f readable [namespace code {
	if {[chan eof $f]} {
	   set x done
	   chan close $f
	} else {
	   lappend l [chan gets $f]
	   incr c







|







6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
    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 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
	    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]
	    vwait z
	    after cancel $timer
	    test servicemode $mode
	    lappend z "del after update"
	}
    }
    set z ""
    set u toplevel
    set timer [after 50 lappend z timeout]
    testservicemode 0







|


|







6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
	    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 [testservicemode 1]
	    vwait z
	    after cancel $timer
	    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
    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
    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)} {







|
|







6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
    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 -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)} {
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
    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 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
    }
    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 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
    }
    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 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
    }
    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]]
    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
    }
    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 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
    }
    return $result
} -cleanup {







|
|














|
|














|
|














|
|
|















|
|







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
    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 -encoding iso8859-1 -blocking 0
    chan configure $f2 -translation lf -encoding iso8859-1 -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
    }
    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 -encoding iso8859-1 -blocking 0
    chan configure $f2 -translation lf -encoding iso8859-1 -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
    }
    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 -encoding iso8859-1 -blocking 0
    chan configure $f2 -translation lf -encoding iso8859-1 -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
    }
    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 -encoding iso8859-1 -blocking 0
    chan configure $f2 -translation lf -encoding iso8859-1 -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
    }
    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 -encoding iso8859-1 -blocking 0
    chan configure $f2 -translation lf -encoding iso8859-1 -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
    }
    return $result
} -cleanup {
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
# 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 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







|







6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
# 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 АА
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
    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} {
    # 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


    chan close $in
    chan close $out
    file size $path(utf8-fcopy.txt)
} 5


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"
    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
    file size $path(kyrillic.txt)

} -result 3



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 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]







|
<






>
>


<
|
>
>



|


<
<




|
|
>
>
>
|
>
>
|
<
>
|
>
>



















|
|







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
    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} -constraints {fcopy} -body {

    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

    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 АА
    close $f
} -constraints {fcopy} -body {


    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 -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

    }
    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 -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]
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
    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] {
	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] {
	vwait [namespace which -variable fcopyTestDone]
    }
    return $fcopyTestDone	;# 0 for plain end of file
} -cleanup {
    catch {chan close $in}
    chan close $out
} -result 0







|



















|







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
    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]} {
	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]} {
	vwait [namespace which -variable fcopyTestDone]
    }
    return $fcopyTestDone	;# 0 for plain end of file
} -cleanup {
    catch {chan close $in}
    chan close $out
} -result 0
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
    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
} -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 {







|







7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
    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}
} -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 {
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
		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]

	chan puts stderr WAITING
	chan event stdin readable bye
	chan puts OK
	vwait forever
    }
    # wait for OK from server.
    chan gets $pipe
    # 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]
    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 {}







|
>


|



|






|
|







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
		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 -myaddr 127.0.0.1 0]
        set port [lindex [chan configure $srv -sockname] 2]
	chan puts stderr WAITING
	chan event stdin readable bye
	puts "OK $port"
	vwait forever
    }
    # wait for OK from server.
    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 $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
} {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]
	exit 1
    }
    proc readit {pipe} {
	variable x
	variable result
	if {[chan eof $pipe]} {
	    set x [catch {chan close $pipe} line]







|







7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
} {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]
	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
    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}}}

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 =







|







7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
    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 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
    #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
# 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 {}







|







7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
    #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 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.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33


















34
35
36



37
38
39
40
41
42
43
# clock.test --
#
#	This test file covers the 'clock' command that manipulates time.
#
# 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) 2004 by 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::*
}

if {[testConstraint win]} {
    if {[catch {
	    ::tcltest::loadTestedCommands
	    package require registry
	}]} {
	namespace eval ::tcl::clock {variable NoRegistry {}}
    }
}

package require msgcat 1.4

testConstraint detroit \
    [expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
testConstraint y2038 \
    [expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]



















# TEST PLAN




# clock-1:
#	[clock format] - tests of bad and empty arguments
#
# clock-2
#	formatting of year, month and day of month
#
# clock-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
# clock.test --
#
#	This test file covers the 'clock' command that manipulates time.
#
# 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 © 2004 Kevin B. Kenny.  All rights reserved.
# 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.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

if {[testConstraint win]} {
    if {[catch {
	    ::tcltest::loadTestedCommands

	}]} {
	# nothing to be done (registry loaded on demand)
    }
}

package require msgcat 1.4

testConstraint detroit \
    [expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
testConstraint y2038 \
    [expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]

# Test with both validity modes - validate on / off:

set valid_mode [::tcl::unsupported::clock::configure -valid]

# Wrapper to show validity mode in the test-case name (for possible errors):
proc test {args} {
  variable valid_mode
  lset args 0 [lindex $args 0].vm:$valid_mode
  tailcall ::tcltest::test {*}$args
}

puts [outputChannel] "  Validity default mode: [expr {$valid_mode ? "on": "off"}]"
testConstraint valid_off [expr {![::tcl::unsupported::clock::configure -valid]}]

if {[namespace which -command ::tcl::unsupported::timerate] ne ""} {
    namespace import ::tcl::unsupported::timerate
}

# TEST PLAN

# clock-0:
#	several base test-cases
#
# clock-1:
#	[clock format] - tests of bad and empty arguments
#
# clock-2
#	formatting of year, month and day of month
#
# clock-3
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252














































253
254

255
256
257
258




259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276


277

278
279
280
281
282
283
284
285
286
287
288
289














290
291
292
293
294
295
296
		  sLongDate "'the' dd''' day of' MMMM yyyy" \
		  sTimeFormat "h:mm:ss tt"] \
	     HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\TimeZoneInformation \
	     [dict create \
		  Bias 300 \
		  StandardBias 0 \
		  DaylightBias -60 \
		  StandardStart \x00\x00\x0b\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00 \
		  DaylightStart \x00\x00\x03\x00\x02\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00]]
}


proc ::testClock::registry { cmd path key } {
    variable reg
    if { $cmd ne {get} } {
	return -code error "test case attempts to write/query the registry"
    }
    if { ![dict exists $reg $path $key] } {
	return -code error "test case attempts to read unknown registry entry $path $key"
    }
    return [dict get $reg $path $key]
}















































# Test some of the basics of [clock format]


test clock-1.0 "clock format - wrong # args" {
    list [catch {clock format} msg] $msg $::errorCode
} {1 {wrong # args: should be "clock format clockval ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?"} {CLOCK wrongNumArgs}}





test clock-1.1 "clock format - bad time" {
    list [catch {clock format foo} msg] $msg
} {1 {expected integer but got "foo"}}

test clock-1.2 "clock format - bad gmt val" {
    list [catch {clock format 0 -gmt foo} msg] $msg
} {1 {expected boolean value but got "foo"}}

test clock-1.3 "clock format - empty val" {
    clock format 0 -gmt 1 -format ""
} {}

test clock-1.4 "clock format - bad flag" {*}{
    -body {
    list [catch {clock format 0 -oops badflag} msg] $msg $::errorCode
    }
    -match glob
    -result {1 {bad option "-oops": must be -format, -gmt, -locale, or -timezone} {CLOCK badOption -oops}}


}


test clock-1.5 "clock format - bad timezone" {
    list [catch {clock format 0 -format "%s" -timezone :NOWHERE} msg] $msg $::errorCode
} {1 {time zone ":NOWHERE" not found} {CLOCK badTimeZone :NOWHERE}}

test clock-1.6 "clock format - gmt + timezone" {
    list [catch {clock format 0 -timezone :GMT -gmt true} msg] $msg $::errorCode
} {1 {cannot use -gmt and -timezone in same call} {CLOCK gmtWithTimezone}}

test clock-1.7 "clock format - option abbreviations" {
    clock format 0 -g true -f "%Y-%m-%d"
} 1970-01-01















# BEGIN testcases2

# Test formatting of Gregorian year, month, day, all formats
# Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY

test clock-2.1 {conversion of 1872-01-01} {







|















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>


|

>
>
>
>

|
|









|
|

<
<
|
>
>
|
>












>
>
>
>
>
>
>
>
>
>
>
>
>
>







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
		  sLongDate "'the' dd''' day of' MMMM yyyy" \
		  sTimeFormat "h:mm:ss tt"] \
	     HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\TimeZoneInformation \
	     [dict create \
		  Bias 300 \
		  StandardBias 0 \
		  DaylightBias -60 \
		  StandardStart \x00\x00\x0B\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00 \
		  DaylightStart \x00\x00\x03\x00\x02\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00]]
}


proc ::testClock::registry { cmd path key } {
    variable reg
    if { $cmd ne {get} } {
	return -code error "test case attempts to write/query the registry"
    }
    if { ![dict exists $reg $path $key] } {
	return -code error "test case attempts to read unknown registry entry $path $key"
    }
    return [dict get $reg $path $key]
}

# Base test cases:

test clock-0.1 "initial: auto-loading of ensemble and stubs on demand" -setup {
    set i [interp create]; # because clock can be used somewhere, test it in new interp:
} -body {
    $i eval {
	lappend ret ens:[namespace ensemble exists ::clock]
	clock seconds; # init ensemble (but not yet stubs, loading of clock.tcl retarded)
	lappend ret ens:[namespace ensemble exists ::clock]
	lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
	clock format -now; # clock.tcl stubs expected
	lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
    }
} -cleanup {
    interp delete $i
} -result {ens:0 ens:1 stubs:0 stubs:1}
test clock-0.1a "initial: safe interpreter shares clock command with parent" -setup {
    set i [interp create]
    $i eval {set sci [interp create -safe]}
} -body {
    $i eval {
	lappend ret ens:[namespace ensemble exists ::clock]
	$sci eval { clock seconds }; # init ensemble (but not yet stubs, loading of clock.tcl retarded)
	lappend ret ens:[namespace ensemble exists ::clock]
	lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
	$sci eval { clock format -now }; # clock.tcl stubs expected
	lappend ret stubs:[expr {[namespace which -command ::tcl::clock::GetSystemTimeZone] ne ""}]
    }
} -cleanup {
    interp delete $i
} -result {ens:0 ens:1 stubs:0 stubs:1}

test clock-0.2 "initial: loading of format/locale does not overwrite interp state (errorInfo)" -setup {
    # be sure - we have no cached locale/msgcat, etc:
    if {[namespace which -command ::tcl::clock::ClearCaches] ne ""} {
	::tcl::clock::ClearCaches
    }
} -body {
    if {[catch {
	return -level 0 -code error -errorcode {EXPERR TEST-ERROR} -errorinfo "ERROR expected error" test
    }]} {
	clock format -now -locale de; # should not overwrite error code/info
	list $::errorCode $::errorInfo
    }
} -result {{EXPERR TEST-ERROR} {ERROR expected error}}

# Test some of the basics of [clock format]

set syntax "clockval|-now ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?"
test clock-1.0 "clock format - wrong # args" {
    list [catch {clock format} msg] $msg $::errorCode
} [subst {1 {wrong # args: should be "clock format $syntax"} {CLOCK wrongNumArgs}}]

test clock-1.0.1 "clock format - wrong # args (compiled ensemble with invalid syntax)" {
    list [catch {clock format 0 -too-few-options-4-test} msg] $msg $::errorCode
} [subst {1 {wrong # args: should be "clock format $syntax"} {CLOCK wrongNumArgs}}]

test clock-1.1 "clock format - bad time" {
    list [catch {clock format foo} msg opt] $msg [dict getd $opt -errorcode {}]
} {1 {bad seconds "foo": must be -now or integer} {CLOCK badOption foo}}

test clock-1.2 "clock format - bad gmt val" {
    list [catch {clock format 0 -gmt foo} msg] $msg
} {1 {expected boolean value but got "foo"}}

test clock-1.3 "clock format - empty val" {
    clock format 0 -gmt 1 -format ""
} {}

test clock-1.4 "clock format - bad flag" {
    # range error message for possible extensions:
    list [catch {clock format 0 -oops badflag} msg] $msg $::errorCode


} [subst {1 {bad option "-oops": must be -format, -gmt, -locale, or -timezone} {CLOCK badOption -oops}}]
test clock-1.4.1 "clock format - unexpected option for this sub-command" {
    # range error message for possible extensions:
    list [catch {clock format 0 -base 0} msg] $msg $::errorCode
} [subst {1 {bad option "-base": must be -format, -gmt, -locale, or -timezone} {CLOCK badOption -base}}]

test clock-1.5 "clock format - bad timezone" {
    list [catch {clock format 0 -format "%s" -timezone :NOWHERE} msg] $msg $::errorCode
} {1 {time zone ":NOWHERE" not found} {CLOCK badTimeZone :NOWHERE}}

test clock-1.6 "clock format - gmt + timezone" {
    list [catch {clock format 0 -timezone :GMT -gmt true} msg] $msg $::errorCode
} {1 {cannot use -gmt and -timezone in same call} {CLOCK gmtWithTimezone}}

test clock-1.7 "clock format - option abbreviations" {
    clock format 0 -g true -f "%Y-%m-%d"
} 1970-01-01

test clock-1.7.1 "clock format - command abbreviations (compat regression test)" {
    clock f 0 -g 1 -f "%Y-%m-%d"
} 1970-01-01

test clock-1.8 "clock format -now" {
    # give one second more for test (if on boundary of the current second):
    set n [clock format [clock seconds] -g 1 -f "%s"]
    expr {[clock format -now -g 1 -f "%s"] in [list $n [incr n]]}
} 1

test clock-1.9 "clock arguments: option doubly present" {
    list [catch {clock format 0 -gmt 1 -gmt 0} result] $result
} {1 {bad option "-gmt": doubly present}}

# BEGIN testcases2

# Test formatting of Gregorian year, month, day, all formats
# Formats tested: %b %B %c %Ec %C %EC %d %Od %e %Oe %h %j %J %m %Om %N %x %Ex %y %Oy %Y %EY

test clock-2.1 {conversion of 1872-01-01} {
15287
15288
15289
15290
15291
15292
15293














































































15294
15295
15296
15297
15298
15299
15300
} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:58 pm 23:59 58 lviii 23:59:58 23:59:58 xxiii h lix m lviii s Thu Jan  1 23:59:58 GMT 1970}
test clock-4.96 { format time of day 23:59:59 } {
    clock format 86399 \
        -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
	  -locale en_US_roman \
        -gmt true
} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:59 pm 23:59 59 lix 23:59:59 23:59:59 xxiii h lix m lix s Thu Jan  1 23:59:59 GMT 1970}














































































# END testcases4

# BEGIN testcases5

# Test formatting of Daylight Saving Time

test clock-5.1 {does Detroit exist} {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







15374
15375
15376
15377
15378
15379
15380
15381
15382
15383
15384
15385
15386
15387
15388
15389
15390
15391
15392
15393
15394
15395
15396
15397
15398
15399
15400
15401
15402
15403
15404
15405
15406
15407
15408
15409
15410
15411
15412
15413
15414
15415
15416
15417
15418
15419
15420
15421
15422
15423
15424
15425
15426
15427
15428
15429
15430
15431
15432
15433
15434
15435
15436
15437
15438
15439
15440
15441
15442
15443
15444
15445
15446
15447
15448
15449
15450
15451
15452
15453
15454
15455
15456
15457
15458
15459
15460
15461
15462
15463
15464
15465
} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:58 pm 23:59 58 lviii 23:59:58 23:59:58 xxiii h lix m lviii s Thu Jan  1 23:59:58 GMT 1970}
test clock-4.96 { format time of day 23:59:59 } {
    clock format 86399 \
        -format {%H %OH %I %OI %k %Ok %l %Ol %M %OM %p %P %r %R %S %OS %T %X %EX %+} \
	  -locale en_US_roman \
        -gmt true
} {23 xxiii 11 xi 23 xxiii 11 xi 59 lix PM pm 11:59:59 pm 23:59 59 lix 23:59:59 23:59:59 xxiii h lix m lix s Thu Jan  1 23:59:59 GMT 1970}

test clock-4.97.1 { format JDN/JD (calendar and astronomical) } {
    clock format 0 -format {%J %EJ %Ej} -gmt true
} {2440588 2440588.0 2440587.5}
test clock-4.97.2 { format JDN/JD (calendar and astronomical) } {
    clock format 43200 -format {%J %EJ %Ej} -gmt true
} {2440588 2440588.5 2440588.0}
test clock-4.97.3 { format JDN/JD (calendar and astronomical) } {
    clock format 86399 -format {%J %EJ %Ej} -gmt true
} {2440588 2440588.99998843 2440588.49998843}
test clock-4.97.4 { format JDN/JD (calendar and astronomical) } {
    clock format 86400 -format {%J %EJ %Ej} -gmt true
} {2440589 2440589.0 2440588.5}
test clock-4.97.5 { format JDN/JD (calendar and astronomical) } {
    clock format 129599 -format {%J %EJ %Ej} -gmt true
} {2440589 2440589.49998843 2440588.99998843}
test clock-4.97.6 { format JDN/JD (calendar and astronomical) } {
    clock format 129600 -format {%J %EJ %Ej} -gmt true
} {2440589 2440589.5 2440589.0}
test clock-4.97.7 { format JDN/JD (calendar and astronomical) } {
    set i 1548249092
    list \
	[clock format $i -format {%J %EJ %Ej} -gmt true] \
	[clock format [incr i] -format {%J %EJ %Ej} -gmt true] \
	[clock format [incr i] -format {%J %EJ %Ej} -gmt true]
} {{2458507 2458507.54967593 2458507.04967593} {2458507 2458507.5496875 2458507.0496875} {2458507 2458507.54969907 2458507.04969907}}
test clock-4.97.8 { format JDN/JD (calendar and astronomical) } {
    set res {}
    foreach i {
	-172800 -129600 -86400 -43200
	-1 0 1 21600 43199 43200 86399
	86400 86401 108000 129600 172800
    } {
	lappend res $i [clock format [expr {-210866803200 - $i}] \
	    -format {%EE %Y-%m-%d %T -- %J %EJ %Ej} -gmt true]
    }
    set res
} [list \
   -172800 {B.C.E. 4713-01-03 00:00:00 -- 0000002 2.0 1.5} \
   -129600 {B.C.E. 4713-01-02 12:00:00 -- 0000001 1.5 1.0} \
    -86400 {B.C.E. 4713-01-02 00:00:00 -- 0000001 1.0 0.5} \
    -43200 {B.C.E. 4713-01-01 12:00:00 -- 0000000 0.5 0.0} \
        -1 {B.C.E. 4713-01-01 00:00:01 -- 0000000 0.00001157 -0.49998843} \
         0 {B.C.E. 4713-01-01 00:00:00 -- 0000000 0.0 -0.5} \
         1 {B.C.E. 4714-12-31 23:59:59 -- -000001 -0.00001157 -0.50001157} \
     21600 {B.C.E. 4714-12-31 18:00:00 -- -000001 -0.25 -0.75} \
     43199 {B.C.E. 4714-12-31 12:00:01 -- -000001 -0.49998843 -0.99998843} \
     43200 {B.C.E. 4714-12-31 12:00:00 -- -000001 -0.5 -1.0} \
     86399 {B.C.E. 4714-12-31 00:00:01 -- -000001 -0.99998843 -1.49998843} \
     86400 {B.C.E. 4714-12-31 00:00:00 -- -000001 -1.0 -1.5} \
     86401 {B.C.E. 4714-12-30 23:59:59 -- -000002 -1.00001157 -1.50001157} \
    108000 {B.C.E. 4714-12-30 18:00:00 -- -000002 -1.25 -1.75} \
    129600 {B.C.E. 4714-12-30 12:00:00 -- -000002 -1.5 -2.0} \
    172800 {B.C.E. 4714-12-30 00:00:00 -- -000002 -2.0 -2.5} \
]
test clock-4.97.9 { format JDN/JD (calendar and astronomical) } {
    set res {}
    foreach i {
	-86400 -43200
	-1 0 1
	43199 43200 43201 86400
    } {
	lappend res $i [clock format [expr {653133196800 + $i}] \
	    -format {%Y-%m-%d %T -- %J %EJ %Ej} -gmt true]
    }
    set res
} [list \
    -86400 {22666-12-19 00:00:00 -- 9999999 9999999.0 9999998.5} \
    -43200 {22666-12-19 12:00:00 -- 9999999 9999999.5 9999999.0} \
        -1 {22666-12-19 23:59:59 -- 9999999 9999999.99998843 9999999.49998843} \
         0 {22666-12-20 00:00:00 -- 10000000 10000000.0 9999999.5} \
         1 {22666-12-20 00:00:01 -- 10000000 10000000.00001157 9999999.50001157} \
     43199 {22666-12-20 11:59:59 -- 10000000 10000000.49998843 9999999.99998843} \
     43200 {22666-12-20 12:00:00 -- 10000000 10000000.5 10000000.0} \
     43201 {22666-12-20 12:00:01 -- 10000000 10000000.50001157 10000000.00001157} \
     86400 {22666-12-21 00:00:00 -- 10000001 10000001.0 10000000.5} \
]

# END testcases4

# BEGIN testcases5

# Test formatting of Daylight Saving Time

test clock-5.1 {does Detroit exist} {
18527
18528
18529
18530
18531
18532
18533




18534
18535
18536
18537
18538
18539
18540
























18541
18542
18543
18544






























































































































































































18545
18546
18547
18548
18549
18550
18551
    clock scan {2147483648} -format %s -gmt true
} 2147483648

test clock-6.8 {input of seconds} {
    clock scan {9223372036854775807} -format %s -gmt true
} 9223372036854775807





test clock-6.9 {input of seconds - overflow} {
    list [catch {clock scan -9223372036854775809 -format %s -gmt true} result] $result
} {1 {integer value too large to represent}}

test clock-6.10 {input of seconds - overflow} {
    list [catch {clock scan 9223372036854775808 -format %s -gmt true} result] $result
} {1 {integer value too large to represent}}

























test clock-6.11 {input of seconds - two values} {
    clock scan {1 2} -format {%s %s} -gmt true
} 2































































































































































































test clock-7.1 {Julian Day} {
    clock scan 0 -format %J -gmt true
} -210866803200

test clock-7.2 {Julian Day} {
    clock format [clock scan 2440588 -format %J -gmt true] \







>
>
>
>

|
|
<

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







18692
18693
18694
18695
18696
18697
18698
18699
18700
18701
18702
18703
18704
18705

18706
18707
18708
18709
18710
18711
18712
18713
18714
18715
18716
18717
18718
18719
18720
18721
18722
18723
18724
18725
18726
18727
18728
18729
18730
18731
18732
18733
18734
18735
18736
18737
18738
18739
18740
18741
18742
18743
18744
18745
18746
18747
18748
18749
18750
18751
18752
18753
18754
18755
18756
18757
18758
18759
18760
18761
18762
18763
18764
18765
18766
18767
18768
18769
18770
18771
18772
18773
18774
18775
18776
18777
18778
18779
18780
18781
18782
18783
18784
18785
18786
18787
18788
18789
18790
18791
18792
18793
18794
18795
18796
18797
18798
18799
18800
18801
18802
18803
18804
18805
18806
18807
18808
18809
18810
18811
18812
18813
18814
18815
18816
18817
18818
18819
18820
18821
18822
18823
18824
18825
18826
18827
18828
18829
18830
18831
18832
18833
18834
18835
18836
18837
18838
18839
18840
18841
18842
18843
18844
18845
18846
18847
18848
18849
18850
18851
18852
18853
18854
18855
18856
18857
18858
18859
18860
18861
18862
18863
18864
18865
18866
18867
18868
18869
18870
18871
18872
18873
18874
18875
18876
18877
18878
18879
18880
18881
18882
18883
18884
18885
18886
18887
18888
18889
18890
18891
18892
18893
18894
18895
18896
18897
18898
18899
18900
18901
18902
18903
18904
18905
18906
18907
18908
18909
18910
18911
18912
18913
18914
18915
18916
18917
18918
18919
18920
18921
18922
18923
18924
18925
18926
18927
18928
18929
18930
18931
18932
18933
    clock scan {2147483648} -format %s -gmt true
} 2147483648

test clock-6.8 {input of seconds} {
    clock scan {9223372036854775807} -format %s -gmt true
} 9223372036854775807

test clock-6.8b "clock scan - bad base" {
    list [catch {clock scan "" -base foo -gmt 1} msg opt] $msg [dict getd $opt -errorcode {}]
} {1 {bad seconds "foo": must be -now or integer} {CLOCK badOption foo}}

test clock-6.9 {input of seconds - overflow} {
    list [catch {clock scan -9223372036854775809 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} {1 {integer value too large to represent} {CLOCK dateTooLarge}}

test clock-6.10 {input of seconds - overflow} {
    list [catch {clock scan 9223372036854775808 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
} {1 {integer value too large to represent} {CLOCK dateTooLarge}}

foreach sign {{} -} {
  test clock-6.10a$sign {input of seconds - overflow, bug [1f40aa83c5]}  {
    list [catch {clock scan ${sign}27670116110564327423 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
  } {1 {integer value too large to represent} {CLOCK dateTooLarge}}
  test clock-6.10b$sign {input of seconds - overflow, bug [1f40aa83c5]} {
    list [catch {clock scan ${sign}27670116110564327424 -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
  } {1 {integer value too large to represent} {CLOCK dateTooLarge}}
  test clock-6.10c$sign {input of seconds - no overflow, bug [1f40aa83c5]} {
    list [catch {clock scan ${sign}[string repeat 9 18] -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
  } [list 0 ${sign}[string repeat 9 18] {}]
  test clock-6.10d$sign {input of seconds - overflow, bug [1f40aa83c5]} {
    list [catch {clock scan ${sign}[string repeat 9 19] -format %s -gmt true} result opt] $result [dict getd $opt -errorcode ""]
  } {1 {integer value too large to represent} {CLOCK dateTooLarge}}
  # both fololowing freescan test don't generate overflow error,
  # since it is a free scan, thus the token is simply not recognized further in yacc lexer,
  # therefore we get parse error (can be surely changed latter):
  test clock-6.10e$sign {input of seconds - overflow (but since freescan parse error, but not boom), bug [1f40aa83c5]} -body {
    list [catch {clock scan ${sign}27670116110564327423 -gmt true} result opt] $result [dict getd $opt -errorcode ""]
  } -match glob -result {1 {unable to convert date-time string "*": syntax error *} {TCL VALUE DATE PARSE}}
  test clock-6.10f$sign {input of seconds - overflow (but since freescan parse error, but not boom), bug [1f40aa83c5]} -body {
    list [catch {clock scan ${sign}27670116110564327424 -gmt true} result opt] $result [dict getd $opt -errorcode ""]
  } -match glob -result {1 {unable to convert date-time string "*": syntax error *} {TCL VALUE DATE PARSE}}
}; unset sign

test clock-6.11 {input of seconds - two values} {
    clock scan {1 2} -format {%s %s} -gmt true
} 2

test clock-6.12.0 {input of short forms of locale token (%b)} {
    list [clock scan "12 Ja 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1] \
	 [clock scan "12 Au 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1]
} {979257600 997574400}
test clock-6.12.1 {input of all forms of unambiguous short locale token (%b)} {
    # find all unambiguous short forms and check it'll be scanned successful and correctly:
    set months {January February March April May June July August September October November December}
    set res {}
    foreach mon $months {
	set i 0
	while {[incr i] < [string length $mon]} {
	    # short month form:
	    set shm [string range $mon 0 $i]
	    # differentiate ambiguous:
	    if {[llength [lsearch -all -glob $months "${shm}*"]] <= 1} {
		# unambiguous (expected date with wull month):
		set e "12 $mon 2001"
	    } else {
		# ambiguous (expected error):
		set e "input string does not match supplied format"
	    }
	    set s "12 $shm 2001"
	    # scan and format with full month name:
	    catch {clock format \
			[clock scan $s -format "%d %b %Y" -locale en_US_roman -gmt 1] \
	          -format "%d %B %Y" -locale en_US_roman -gmt 1} t
	    # check it corresponds the full form:
	    if {$t ne $e} {
		lappend res "unexpected result converting $s, expected \"$e\", got \"$t\""
	    }
	}
    }
    set res
} {}
test clock-6.13 {input of lowercase locale token (%b)} {
    list [clock scan "12 ja 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1] \
	 [clock scan "12 au 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1]
} {979257600 997574400}
test clock-6.14 {input of uppercase locale token (%b)} {
    list [clock scan "12 JA 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1] \
	 [clock scan "12 AU 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1]
} {979257600 997574400}
test clock-6.15 {input of ambiguous short locale token (%b)} {
    list [catch {
	clock scan "12 J 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1
    } result] $result $errorCode
} {1 {input string does not match supplied format} {CLOCK badInputString}}
test clock-6.16 {input of ambiguous short locale token (%b)} {
    list [catch {
	clock scan "12 Ju 2001" -format "%d %b %Y" -locale en_US_roman -gmt 1
    } result] $result $errorCode
} {1 {input string does not match supplied format} {CLOCK badInputString}}

test clock-6.17 {spaces are always optional in non-strict mode (default)} {
    list [clock scan "2009-06-30T18:30:00+02:00" -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
	 [clock scan "2009-06-30T18:30:00  +02:00" -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
	 [clock scan "2009-06-30T18:30:00Z" -format "%Y-%m-%dT%H:%M:%S%z" -timezone CET] \
	 [clock scan "2009-06-30T18:30:00  Z" -format "%Y-%m-%dT%H:%M:%S%z" -timezone CET]
} {1246379400 1246379400 1246386600 1246386600}

test clock-6.18 {zone token (%z) is optional} {
    list [clock scan "2009-06-30T18:30:00 -01:00" -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
         [clock scan "2009-06-30T18:30:00" -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
	 [clock scan "  2009-06-30T18:30:00  " -format "%Y-%m-%dT%H:%M:%S%z" -gmt 1] \
} {1246390200 1246386600 1246386600}

test clock-6.19 {no token parsing} {
    list [catch { clock scan "%E%O%" -format "%E%O%" }] \
         [catch { clock scan "...%..." -format "...%%..." }]
} {0 0}

test clock-6.20 {special char tokens %n, %t} {
    clock scan "30\t06\t2009\n18\t30" -format "%d%t%m%t%Y%n%H%t%M" -gmt 1
} 1246386600

# Hi, Jeff!
proc _testStarDates {s {days {366*2}} {step {86400}}} {
    set step [expr {int($step * 86400)}]
    # reconvert - arrange in order of stardate:
    set s [set i [clock scan [clock format $s -f "%Q" -g 1] -g 1]]
    # test:
    set wrong {}
    while {$i < $s + $days*86400} {
	set d [clock format $i -f "%Q" -g 1]
	if {![regexp {^Stardate \d+\.\d$} $d]} {
	    lappend wrong "wrong: $d -- ($i) -- [clock format $i -g 1]"
	}
	if {[catch {
	    set i2 [clock scan $d -f "%Q" -g 1]
	} msg]} {
	    lappend wrong "$d -- ($i) -- [clock format $i -g 1]: $msg"
	}
	if {$i != $i2} {
	    lappend wrong "$d -- ($i != $i2) -- [clock format $i -g 1]"
	}
	incr i $step
    }
    join $wrong \n
}
test clock-6.21.0 {Stardate 0 day} {
    list [set d [clock format -757382400 -format "%Q" -gmt 1]] \
         [clock scan $d -format "%Q" -gmt 1]
} [list "Stardate 00000.0" -757382400]
test clock-6.21.0.1 {Stardate 0.1 - 1.9 (test negative clock value -> positive Stardate)} {
    _testStarDates -757382400 2 0.1
} {}
test clock-6.21.0.2 {Stardate 10000.1 - 10002.9 (test negative clock value -> positive Stardate)} {
    _testStarDates [clock scan "Stardate 10000.1" -f %Q -g 1] 3 0.1
} {}
test clock-6.21.0.3 {Stardate 80000.1 - 80002.9 (test positive clock value)} {
    _testStarDates [clock scan "Stardate 80001.1" -f %Q -g 1] 3 0.1
} {}
test clock-6.21.1 {Stardate} {
    list [set d [clock format 1482857280 -format "%Q" -gmt 1]] \
         [clock scan $d -format "%Q" -gmt 1]
} [list "Stardate 70986.7" 1482857280]
test clock-6.21.2 {Stardate next time} {
    list [set d [clock format 1482865920 -format "%Q" -gmt 1]] \
         [clock scan $d -format "%Q" -gmt 1]
} [list "Stardate 70986.8" 1482865920]
test clock-6.21.3 {Stardate correct scan over year (leap year, begin, middle and end of the year)} {
    _testStarDates [clock scan "01.01.2016" -f "%d.%m.%Y" -g 1] [expr {366*2}] 1
} {}
rename _testStarDates {}

test clock-6.22.1 {Greedy match} {
    clock format [clock scan "111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 00:00:00 GMT 2001}
test clock-6.22.2 {Greedy match} {
    clock format [clock scan "1111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Thu Jan 11 00:00:00 GMT 2001}
test clock-6.22.3 {Greedy match} {
    clock format [clock scan "11111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Sun Nov 11 00:00:00 GMT 2001}
test clock-6.22.4 {Greedy match} {
    clock format [clock scan "111111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Fri Nov 11 00:00:00 GMT 2011}
test clock-6.22.5 {Greedy match} {
    clock format [clock scan "1 1 1" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 00:00:00 GMT 2001}
test clock-6.22.6 {Greedy match} {
    clock format [clock scan "111 1" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Thu Jan 11 00:00:00 GMT 2001}
test clock-6.22.7 {Greedy match} {
    clock format [clock scan "1 111" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Thu Nov 01 00:00:00 GMT 2001}
test clock-6.22.8 {Greedy match} {
    clock format [clock scan "1 11 1" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Thu Nov 01 00:00:00 GMT 2001}
test clock-6.22.9 {Greedy match} {
    clock format [clock scan "1 11 11" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Tue Nov 01 00:00:00 GMT 2011}
test clock-6.22.10 {Greedy match} {
    clock format [clock scan "11 11 11" -format "%d%m%y" -gmt 1] -locale en -gmt 1
} {Fri Nov 11 00:00:00 GMT 2011}
test clock-6.22.11 {Greedy match} {
    clock format [clock scan "1111 120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Sat Jan 01 01:02:00 GMT 2011}
test clock-6.22.12 {Greedy match} {
    clock format [clock scan "11 1 120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 01:02:00 GMT 2001}
test clock-6.22.13 {Greedy match} {
    clock format [clock scan "1 11 120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 01:02:00 GMT 2001}
test clock-6.22.14 {Greedy match} {
    clock format [clock scan "111120" -format "%y%m%d%H%M%S" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 01:02:00 GMT 2001}
test clock-6.22.15 {Greedy match} {
    clock format [clock scan "1111120" -format "%y%m%d%H%M%S" -gmt 1] -locale en -gmt 1
} {Sat Jan 01 01:02:00 GMT 2011}
test clock-6.22.16 {Greedy match} {
    clock format [clock scan "11121120" -format "%y%m%d%H%M%S" -gmt 1] -locale en -gmt 1
} {Thu Dec 01 01:02:00 GMT 2011}
test clock-6.22.17 {Greedy match} {
    clock format [clock scan "111213120" -format "%y%m%d%H%M%S" -gmt 1] -locale en -gmt 1
} {Tue Dec 13 01:02:00 GMT 2011}
test clock-6.22.17.1 {Greedy match (space wins as date-time separator)} {
    clock format [clock scan "1112 13120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Sun Jan 02 13:12:00 GMT 2011}
test clock-6.22.18 {Greedy match (second space wins as date-time separator)} {
    clock format [clock scan "1112 13 120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Tue Dec 13 01:02:00 GMT 2011}
test clock-6.22.19 {Greedy match (space wins as date-time separator)} {
    clock format [clock scan "111 213120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Mon Jan 01 21:31:20 GMT 2001}
test clock-6.22.20 {Greedy match (second space wins as date-time separator)} {
    clock format [clock scan "111 2 13120" -format "%y%m%d %H%M%S" -gmt 1] -locale en -gmt 1
} {Sun Jan 02 13:12:00 GMT 2011}


test clock-7.1 {Julian Day} {
    clock scan 0 -format %J -gmt true
} -210866803200

test clock-7.2 {Julian Day} {
    clock format [clock scan 2440588 -format %J -gmt true] \
18592
18593
18594
18595
18596
18597
18598



































































































18599
18600
18601
18602
18603
18604
18605
	[clock scan {0 2440589} -format {%s %J} -gmt true]
} {86400 0 86400 0}

test clock-7.9 {Julian Day, two values} {
    clock scan {2440588 2440589} -format {%J %J} -gmt true
} 86400




































































































# BEGIN testcases8

# Test parsing of ccyymmdd

test clock-8.1 {parse ccyymmdd} {
    clock scan {1970 Jan 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
} 86400







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







18974
18975
18976
18977
18978
18979
18980
18981
18982
18983
18984
18985
18986
18987
18988
18989
18990
18991
18992
18993
18994
18995
18996
18997
18998
18999
19000
19001
19002
19003
19004
19005
19006
19007
19008
19009
19010
19011
19012
19013
19014
19015
19016
19017
19018
19019
19020
19021
19022
19023
19024
19025
19026
19027
19028
19029
19030
19031
19032
19033
19034
19035
19036
19037
19038
19039
19040
19041
19042
19043
19044
19045
19046
19047
19048
19049
19050
19051
19052
19053
19054
19055
19056
19057
19058
19059
19060
19061
19062
19063
19064
19065
19066
19067
19068
19069
19070
19071
19072
19073
19074
19075
19076
19077
19078
19079
19080
19081
19082
19083
19084
19085
19086
	[clock scan {0 2440589} -format {%s %J} -gmt true]
} {86400 0 86400 0}

test clock-7.9 {Julian Day, two values} {
    clock scan {2440588 2440589} -format {%J %J} -gmt true
} 86400

test clock-7.10 {Julian Day, negative amount} {
    # Note: %J does not accept negative input;
    # add negative amounts to Julian day 0 instead
    set s0 [clock scan 0 -format %J -gmt true]
    set J0 [scan [clock format $s0 -format %J -gmt true] %lld]
    set s0m1d [clock add $s0 -1 days -timezone :UTC]
    set s0m24h [clock add $s0 -24 hours -timezone :UTC]
    set J0m24h [scan [clock format $s0m24h -format %J -gmt true] %lld]
    set s0m1s [clock add $s0 -1 seconds -timezone :UTC]
    set J0m1s [scan [clock format $s0m1s -format %J -gmt true] %lld]
    list $s0m1d $s0m24h $J0m24h $s0m1s $J0m1s $s0 $J0 \
	[::tcl::mathop::== $s0m1d $s0m24h] [::tcl::mathop::== $J0m24h $J0m1s]
} [list -210866889600 -210866889600 -1 -210866803201 -1 -210866803200 0 1 1]

test clock-7.11.1 {Calendar vs Astronomical Julian Day (without and with time fraction)} {
    list \
	[clock scan {2440588}   -format {%J}  -gmt true] \
	[clock scan {2440588}   -format {%EJ} -gmt true] \
	[clock scan {2440588}   -format {%Ej} -gmt true] \
	[clock scan {2440588.5} -format {%EJ} -gmt true] \
	[clock scan {2440588.5} -format {%Ej} -gmt true] \
} {0 0 43200 43200 86400}

test clock-7.11.2 {Astronomical JDN/JD} {
    clock scan 0 -format %Ej -gmt true
} -210866760000

test clock-7.12 {Astronomical JDN/JD} {
    clock format [clock scan 2440587.5 -format %Ej -gmt true] \
	-format "%Y-%m-%d %T" -gmt true
} "1970-01-01 00:00:00"

test clock-7.13 {Astronomical JDN/JD} {
    clock format [clock scan 2451544.5 -format %Ej -gmt true] \
	-format "%Y-%m-%d %T" -gmt true
} "2000-01-01 00:00:00"

test clock-7.13.1 {Astronomical JDN/JD} {
    clock format [clock scan 2488069.5 -format %Ej -gmt true] \
	-format "%Y-%m-%d %T" -gmt true
} "2100-01-01 00:00:00"

test clock-7.14 {Astronomical JDN/JD} {
    clock format [clock scan 5373483.5 -format %Ej -gmt true] \
	-format "%Y-%m-%d %T" -gmt true
} "9999-12-31 00:00:00"

test clock-7.14.1 {Astronomical JDN/JD} {
    clock format [clock scan 5373484 -format %Ej -gmt true] \
	-format "%Y-%m-%d %T" -gmt true
} "9999-12-31 12:00:00"
test clock-7.14.2 {Astronomical JDN/JD} {
    clock format [clock scan 5373484.49999 -format %Ej -gmt true] \
	-format "%Y-%m-%d %T" -gmt true
} "9999-12-31 23:59:59"

test clock-7.15 {Astronomical JDN/JD, bad} {
    list [catch {
	clock scan bogus -format %Ej
    } result] $result $errorCode
} {1 {input string does not match supplied format} {CLOCK badInputString}}

test clock-7.16 {Astronomical JDN/JD, overflow} {
    list [catch {
	clock scan 5373484.5 -format %Ej
    } result] $result $errorCode \
    [catch {
	clock scan 5373485 -format %Ej
    } result] $result $errorCode \
    [catch {
	clock scan 2147483648 -format %Ej
    } result] $result $errorCode \
    [catch {
	clock scan 2147483648.5 -format %Ej
    } result] $result $errorCode
} [lrepeat 4 1 {requested date too large to represent} {CLOCK dateTooLarge}]

test clock-7.18 {Astronomical JDN/JD, same precedence as seconds (last wins} {
    list [clock scan {2440588 86400} -format {%Ej %s} -gmt true] \
	[clock scan {2440589 0} -format {%Ej %s} -gmt true] \
	[clock scan {86400 2440588} -format {%s %Ej} -gmt true] \
	[clock scan {0 2440589} -format {%s %Ej} -gmt true]
} {86400 0 43200 129600}

test clock-7.19 {Astronomical JDN/JD, two values} {
    clock scan {2440588 2440589} -format {%Ej %Ej} -gmt true
} 129600

test clock-7.20 {all JDN/JD are signed (and extended accept floats)} {
    set res {}
    foreach i {%J %EJ %Ej} {
	lappend res [clock scan "-1" -format $i -gmt 1]
    }
    foreach i {%EJ %Ej} {
	lappend res [clock scan "-1.5" -format $i -gmt 1]
    }
    set res
} {-210866889600 -210866889600 -210866846400 -210866846400 -210866803200}

# BEGIN testcases8

# Test parsing of ccyymmdd

test clock-8.1 {parse ccyymmdd} {
    clock scan {1970 Jan 02} -format {%C%y %b %d} -locale en_US_roman -gmt 1
} 86400
21002
21003
21004
21005
21006
21007
21008
21009

21010

21011











21012
21013
21014
21015
21016
21017
21018
} 1009756800
# END testcases8

test clock-9.1 {seconds take precedence over ccyymmdd} {
    clock scan {0 20000101} -format {%s %Y%m%d} -gmt true
} 0

test clock-9.2 {Julian day takes precedence over ccyymmdd} {

    clock scan {2440588 20000101} -format {%J %Y%m%d} -gmt true

} 0












# Test parsing of ccyyddd

test clock-10.1 {parse ccyyddd} {
    clock scan {1970 001} -format {%Y %j} -locale en_US_roman -gmt 1
} 0
test clock-10.2 {parse ccyyddd} {







|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>







21483
21484
21485
21486
21487
21488
21489
21490
21491
21492
21493
21494
21495
21496
21497
21498
21499
21500
21501
21502
21503
21504
21505
21506
21507
21508
21509
21510
21511
21512
} 1009756800
# END testcases8

test clock-9.1 {seconds take precedence over ccyymmdd} {
    clock scan {0 20000101} -format {%s %Y%m%d} -gmt true
} 0

test clock-9.2 {Calendar julian day takes precedence over ccyymmdd} {
    list \
	[clock scan {2440588 20000101} -format {%J %Y%m%d} -gmt true] \
	[clock scan {2440588 20000101} -format {%EJ %Y%m%d} -gmt true]
} {0 0}
test clock-9.2.1 {Calendar julian day (with time fraction) takes precedence over date-time} {
    list \
	[clock scan {2440588.0 20000101 010203} -format {%EJ %Y%m%d %H%M%S} -gmt true] \
	[clock scan {2440588.5 20000101 010203} -format {%EJ %Y%m%d %H%M%S} -gmt true]

} {0 43200}
test clock-9.3 {Astro julian day takes always precedence over date-time} {
    list \
	[clock scan {2440587.5 20000101 010203} -format {%Ej %Y%m%d %H%M%S} -gmt true] \
	[clock scan {2440588 20000101 010203} -format {%Ej %Y%m%d %H%M%S} -gmt true]
} {0 43200}

# Test parsing of ccyyddd

test clock-10.1 {parse ccyyddd} {
    clock scan {1970 001} -format {%Y %j} -locale en_US_roman -gmt 1
} 0
test clock-10.2 {parse ccyyddd} {
21045
21046
21047
21048
21049
21050
21051
21052
21053





21054
21055
21056
21057
21058
21059
21060
21061
21062
21063
21064
21065
21066
21067
21068
21069
21070
21071
21072
21073
21074
21075
21076
21077
21078
21079
21080
21081
21082
21083
21084
21085
21086
21087
21088
21089
21090
21091
21092
21093
21094
21095
21096
21097
21098
21099
21100
21101
21102
21103
21104
21105
21106
21107
21108
21109
21110
21111
21112
21113
21114
21115
21116
21117
21118
21119
21120
21121
21122
21123
21124
21125


21126
21127
21128
21129
21130
21131
21132
test clock-10.10 {julian day takes precedence over ccyyddd} {
    list [clock scan {2440588 2000001} -format {%J %Y%j} -gmt true] \
	 [clock scan {2000001 2440588} -format {%Y%j %J} -gmt true]
} {0 0}

# BEGIN testcases11

# Test precedence among yyyymmdd and yyyyddd






test clock-11.1 {precedence of ccyyddd and ccyymmdd} {
    clock scan 19700101002 -format %Y%m%d%j -gmt 1
} 86400
test clock-11.2 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01197001002 -format %m%Y%d%j -gmt 1
} 86400
test clock-11.3 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01197001002 -format %d%Y%m%j -gmt 1
} 86400
test clock-11.4 {precedence of ccyyddd and ccyymmdd} {
    clock scan 00219700101 -format %j%Y%m%d -gmt 1
} 0
test clock-11.5 {precedence of ccyyddd and ccyymmdd} {
    clock scan 19700100201 -format %Y%m%j%d -gmt 1
} 0
test clock-11.6 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01197000201 -format %m%Y%j%d -gmt 1
} 0
test clock-11.7 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01197000201 -format %d%Y%j%m -gmt 1
} 0
test clock-11.8 {precedence of ccyyddd and ccyymmdd} {
    clock scan 00219700101 -format %j%Y%d%m -gmt 1
} 0
test clock-11.9 {precedence of ccyyddd and ccyymmdd} {
    clock scan 19700101002 -format %Y%d%m%j -gmt 1
} 86400
test clock-11.10 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01011970002 -format %m%d%Y%j -gmt 1
} 86400
test clock-11.11 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01011970002 -format %d%m%Y%j -gmt 1
} 86400
test clock-11.12 {precedence of ccyyddd and ccyymmdd} {
    clock scan 00201197001 -format %j%m%Y%d -gmt 1
} 0
test clock-11.13 {precedence of ccyyddd and ccyymmdd} {
    clock scan 19700100201 -format %Y%d%j%m -gmt 1
} 0
test clock-11.14 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01010021970 -format %m%d%j%Y -gmt 1
} 86400
test clock-11.15 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01010021970 -format %d%m%j%Y -gmt 1
} 86400
test clock-11.16 {precedence of ccyyddd and ccyymmdd} {
    clock scan 00201011970 -format %j%m%d%Y -gmt 1
} 0
test clock-11.17 {precedence of ccyyddd and ccyymmdd} {
    clock scan 19700020101 -format %Y%j%m%d -gmt 1
} 0
test clock-11.18 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01002197001 -format %m%j%Y%d -gmt 1
} 0
test clock-11.19 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01002197001 -format %d%j%Y%m -gmt 1
} 0
test clock-11.20 {precedence of ccyyddd and ccyymmdd} {
    clock scan 00201197001 -format %j%d%Y%m -gmt 1
} 0
test clock-11.21 {precedence of ccyyddd and ccyymmdd} {
    clock scan 19700020101 -format %Y%j%d%m -gmt 1
} 0
test clock-11.22 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01002011970 -format %m%j%d%Y -gmt 1
} 0
test clock-11.23 {precedence of ccyyddd and ccyymmdd} {
    clock scan 01002011970 -format %d%j%m%Y -gmt 1
} 0
test clock-11.24 {precedence of ccyyddd and ccyymmdd} {
    clock scan 00201011970 -format %j%d%m%Y -gmt 1
} 0


# END testcases11

# BEGIN testcases12

# Test parsing of ccyyWwwd

test clock-12.1 {parse ccyyWwwd} {







|

>
>
>
>
>
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
|

|
>
>







21539
21540
21541
21542
21543
21544
21545
21546
21547
21548
21549
21550
21551
21552
21553
21554
21555
21556
21557
21558
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576
21577
21578
21579
21580
21581
21582
21583
21584
21585
21586
21587
21588
21589
21590
21591
21592
21593
21594
21595
21596
21597
21598
21599
21600
21601
21602
21603
21604
21605
21606
21607
21608
21609
21610
21611
21612
21613
21614
21615
21616
21617
21618
21619
21620
21621
21622
21623
21624
21625
21626
21627
21628
21629
21630
21631
21632
21633
test clock-10.10 {julian day takes precedence over ccyyddd} {
    list [clock scan {2440588 2000001} -format {%J %Y%j} -gmt true] \
	 [clock scan {2000001 2440588} -format {%Y%j %J} -gmt true]
} {0 0}

# BEGIN testcases11

# Test precedence yyyymmdd over yyyyddd

if {!$valid_mode} {
    set res {-result 0}
} else {
    set res {-returnCodes error -result "unable to convert input string: ambiguous day"}
}
test clock-11.1 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 19700101002 -format %Y%m%d%j -gmt 1
} {*}$res
test clock-11.2 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01197001002 -format %m%Y%d%j -gmt 1
} {*}$res
test clock-11.3 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01197001002 -format %d%Y%m%j -gmt 1
} {*}$res
test clock-11.4 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 00219700101 -format %j%Y%m%d -gmt 1
} {*}$res
test clock-11.5 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 19700100201 -format %Y%m%j%d -gmt 1
} {*}$res
test clock-11.6 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01197000201 -format %m%Y%j%d -gmt 1
} {*}$res
test clock-11.7 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01197000201 -format %d%Y%j%m -gmt 1
} {*}$res
test clock-11.8 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 00219700101 -format %j%Y%d%m -gmt 1
} {*}$res
test clock-11.9 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 19700101002 -format %Y%d%m%j -gmt 1
} {*}$res
test clock-11.10 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01011970002 -format %m%d%Y%j -gmt 1
} {*}$res
test clock-11.11 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01011970002 -format %d%m%Y%j -gmt 1
} {*}$res
test clock-11.12 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 00201197001 -format %j%m%Y%d -gmt 1
} {*}$res
test clock-11.13 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 19700100201 -format %Y%d%j%m -gmt 1
} {*}$res
test clock-11.14 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01010021970 -format %m%d%j%Y -gmt 1
} {*}$res
test clock-11.15 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01010021970 -format %d%m%j%Y -gmt 1
} {*}$res
test clock-11.16 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 00201011970 -format %j%m%d%Y -gmt 1
} {*}$res
test clock-11.17 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 19700020101 -format %Y%j%m%d -gmt 1
} {*}$res
test clock-11.18 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01002197001 -format %m%j%Y%d -gmt 1
} {*}$res
test clock-11.19 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01002197001 -format %d%j%Y%m -gmt 1
} {*}$res
test clock-11.20 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 00201197001 -format %j%d%Y%m -gmt 1
} {*}$res
test clock-11.21 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 19700020101 -format %Y%j%d%m -gmt 1
} {*}$res
test clock-11.22 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01002011970 -format %m%j%d%Y -gmt 1
} {*}$res
test clock-11.23 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 01002011970 -format %d%j%m%Y -gmt 1
} {*}$res
test clock-11.24 {precedence of ccyymmdd over ccyyddd} -body {
    clock scan 00201011970 -format %j%d%m%Y -gmt 1
} {*}$res

unset -nocomplain res
# END testcases11

# BEGIN testcases12

# Test parsing of ccyyWwwd

test clock-12.1 {parse ccyyWwwd} {
21415
21416
21417
21418
21419
21420
21421
21422
21423
21424
21425
21426
21427
21428
21429
21430
21431
21432
21433
    clock scan {2002 W01 i} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
} 1009756800
test clock-12.96 {parse ccyyWwwd} {
    clock scan {2002 W01 i} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
} 1009756800
# END testcases12

test clock-13.1 {test that %s takes precedence over ccyyWwwd} {
    list [clock scan {0 2000W011} -format {%s %GW%V%u} -gmt true] \
	 [clock scan {2000W011 0} -format {%GW%V%u %s} -gmt true]
} {0 0}
test clock-13.2 {test that %J takes precedence over ccyyWwwd} {
    list [clock scan {2440588 2000W011} -format {%J %GW%V%u} -gmt true] \
	 [clock scan {2000W011 2440588} -format {%GW%V%u %J} -gmt true]
} {0 0}
test clock-13.3 {invalid weekday} {
    catch {clock scan 2000W018 -format %GW%V%u -gmt true} result
    list $result $::errorCode
} {{day of week is greater than 7} {CLOCK badDayOfWeek}}







|



|







21916
21917
21918
21919
21920
21921
21922
21923
21924
21925
21926
21927
21928
21929
21930
21931
21932
21933
21934
    clock scan {2002 W01 i} -format {%G W%V %Ou} -locale en_US_roman -gmt 1
} 1009756800
test clock-12.96 {parse ccyyWwwd} {
    clock scan {2002 W01 i} -format {%G W%V %Ow} -locale en_US_roman -gmt 1
} 1009756800
# END testcases12

test clock-13.1 {test that %s takes precedence over ccyyWwwd} valid_off {
    list [clock scan {0 2000W011} -format {%s %GW%V%u} -gmt true] \
	 [clock scan {2000W011 0} -format {%GW%V%u %s} -gmt true]
} {0 0}
test clock-13.2 {test that %J takes precedence over ccyyWwwd} valid_off {
    list [clock scan {2440588 2000W011} -format {%J %GW%V%u} -gmt true] \
	 [clock scan {2000W011 2440588} -format {%GW%V%u %J} -gmt true]
} {0 0}
test clock-13.3 {invalid weekday} {
    catch {clock scan 2000W018 -format %GW%V%u -gmt true} result
    list $result $::errorCode
} {{day of week is greater than 7} {CLOCK badDayOfWeek}}
23755
23756
23757
23758
23759
23760
23761
23762
23763
23764
23765
23766
23767
23768
23769
} {0 0}

test clock-15.2 {yymmdd precedence below julian day} {
    list [clock scan {2440588 000101} -format {%J %y%m%d} -gmt true] \
	[clock scan {000101 2440588} -format {%y%m%d %J} -gmt true]
} {0 0}

test clock-15.3 {yymmdd precedence below yyyyWwwd} {
    list [clock scan {1970W014000101} -format {%GW%V%u%y%m%d} -gmt true] \
	[clock scan {0001011970W014} -format {%y%m%d%GW%V%u} -gmt true]
} {0 0}

# Test parsing of yyddd

test clock-16.1 {parse yyddd} {







|







24256
24257
24258
24259
24260
24261
24262
24263
24264
24265
24266
24267
24268
24269
24270
} {0 0}

test clock-15.2 {yymmdd precedence below julian day} {
    list [clock scan {2440588 000101} -format {%J %y%m%d} -gmt true] \
	[clock scan {000101 2440588} -format {%y%m%d %J} -gmt true]
} {0 0}

test clock-15.3 {yymmdd precedence below yyyyWwwd} valid_off {
    list [clock scan {1970W014000101} -format {%GW%V%u%y%m%d} -gmt true] \
	[clock scan {0001011970W014} -format {%y%m%d%GW%V%u} -gmt true]
} {0 0}

# Test parsing of yyddd

test clock-16.1 {parse yyddd} {
23795
23796
23797
23798
23799
23800
23801
23802
23803
23804
23805
23806
23807
23808
23809
    list [clock scan {0 00001} -format {%s %y%j} -gmt true] \
	 [clock scan {00001 0} -format {%y%j %s} -gmt true]
} {0 0}
test clock-16.10 {julian day takes precedence over yyddd} {
    list [clock scan {2440588 00001} -format {%J %y%j} -gmt true] \
	 [clock scan {00001 2440588} -format {%Y%j %J} -gmt true]
} {0 0}
test clock-16.11 {yyddd precedence below yyyyWwwd} {
    list [clock scan {1970W01400001} -format {%GW%V%u%y%j} -gmt true] \
	[clock scan {000011970W014} -format {%y%j%GW%V%u} -gmt true]
} {0 0}

# BEGIN testcases17

# Test parsing of yyWwwd







|







24296
24297
24298
24299
24300
24301
24302
24303
24304
24305
24306
24307
24308
24309
24310
    list [clock scan {0 00001} -format {%s %y%j} -gmt true] \
	 [clock scan {00001 0} -format {%y%j %s} -gmt true]
} {0 0}
test clock-16.10 {julian day takes precedence over yyddd} {
    list [clock scan {2440588 00001} -format {%J %y%j} -gmt true] \
	 [clock scan {00001 2440588} -format {%Y%j %J} -gmt true]
} {0 0}
test clock-16.11 {yyddd precedence below yyyyWwwd} valid_off {
    list [clock scan {1970W01400001} -format {%GW%V%u%y%j} -gmt true] \
	[clock scan {000011970W014} -format {%y%j%GW%V%u} -gmt true]
} {0 0}

# BEGIN testcases17

# Test parsing of yyWwwd
24096
24097
24098
24099
24100
24101
24102
24103
24104
24105
24106
24107
24108
24109
24110
24111
24112
24113
24114
24115
24116
24117
24118
24119
24120
24121
24122
test clock-17.96 {parse yyWwwd} {
    clock scan {02 W01 i} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
} 1009756800
# END testcases17

# Test precedence of yyWwwd

test clock-18.1 {seconds take precedence over yyWwwd} {
    list [clock scan {0 00W014} -format {%s %gW%V%u} -gmt true] \
	 [clock scan {00W014 0} -format {%gW%V%u %s} -gmt true]
} {0 0}
test clock-18.2 {julian day takes precedence over yyddd} {
    list [clock scan {2440588 00W014} -format {%J %gW%V%u} -gmt true] \
	 [clock scan {00W014 2440588} -format {%gW%V%u %J} -gmt true]
} {0 0}
test clock-18.3 {yyWwwd precedence below yyyymmdd} {
    list [clock scan {19700101 00W014} -format {%Y%m%d %gW%V%u} -gmt true] \
	[clock scan {00W014 19700101} -format {%gW%V%u %Y%m%d} -gmt true]
} {0 0}
test clock-18.4 {yyWwwd precedence below yyyyddd} {
    list [clock scan {1970001 00W014} -format {%Y%j %gW%V%u} -gmt true] \
	[clock scan {00W014 1970001} -format {%gW%V%u %Y%j} -gmt true]
} {0 0}

# BEGIN testcases19

# Test parsing of mmdd







|







|



|







24597
24598
24599
24600
24601
24602
24603
24604
24605
24606
24607
24608
24609
24610
24611
24612
24613
24614
24615
24616
24617
24618
24619
24620
24621
24622
24623
test clock-17.96 {parse yyWwwd} {
    clock scan {02 W01 i} -format {%g W%V %Ow} -locale en_US_roman -gmt 1
} 1009756800
# END testcases17

# Test precedence of yyWwwd

test clock-18.1 {seconds take precedence over yyWwwd} valid_off {
    list [clock scan {0 00W014} -format {%s %gW%V%u} -gmt true] \
	 [clock scan {00W014 0} -format {%gW%V%u %s} -gmt true]
} {0 0}
test clock-18.2 {julian day takes precedence over yyddd} {
    list [clock scan {2440588 00W014} -format {%J %gW%V%u} -gmt true] \
	 [clock scan {00W014 2440588} -format {%gW%V%u %J} -gmt true]
} {0 0}
test clock-18.3 {yyWwwd precedence below yyyymmdd} valid_off {
    list [clock scan {19700101 00W014} -format {%Y%m%d %gW%V%u} -gmt true] \
	[clock scan {00W014 19700101} -format {%gW%V%u %Y%m%d} -gmt true]
} {0 0}
test clock-18.4 {yyWwwd precedence below yyyyddd} valid_off {
    list [clock scan {1970001 00W014} -format {%Y%j %gW%V%u} -gmt true] \
	[clock scan {00W014 1970001} -format {%gW%V%u %Y%j} -gmt true]
} {0 0}

# BEGIN testcases19

# Test parsing of mmdd
25920
25921
25922
25923
25924
25925
25926





25927
25928
25929
25930
25931
25932
25933
25934
25935
25936
25937
25938
25939
25940
25941
25942
25943
25944
25945
25946
25947
25948
25949
25950
25951
25952
25953
25954
25955
25956
25957
25958
25959
25960
25961
25962

25963
25964
25965
25966
25967
25968
25969
    clock scan vii -format %Ou -locale en_US_roman -gmt 1 -base 1009411200
} 1009670400
test clock-26.48 {parse naked day of week} {
    clock scan ? -format %Ow -locale en_US_roman -gmt 1 -base 1009411200
} 1009670400
# END testcases26






test clock-27.1 {seconds take precedence over naked weekday} {
    list [clock scan {0 1} -format {%s %u} -gmt true -base 0] \
	 [clock scan {1 0} -format {%u %s} -gmt true -base 0]
} {0 0}
test clock-27.2 {julian day takes precedence over naked weekday} {
    list [clock scan {2440588 1} -format {%J %u} -gmt true -base 0] \
	 [clock scan {1 2440588} -format {%u %J} -gmt true -base 0]
} {0 0}
test clock-27.3 {yyyymmdd over naked weekday} {
    list [clock scan {19700101 1} -format {%Y%m%d %u} -gmt true -base 0] \
	[clock scan {1 19700101} -format {%u %Y%m%d} -gmt true -base 0]
} {0 0}
test clock-27.4 {yyyyddd over naked weekday} {
    list [clock scan {1970001 1} -format {%Y%j %u} -gmt true -base 0] \
	[clock scan {1 1970001} -format {%u %Y%j} -gmt true -base 0]
} {0 0}
test clock-27.5 {yymmdd over naked weekday} {
    list [clock scan {700101 1} -format {%y%m%d %u} -gmt true -base 0] \
	[clock scan {1 700101} -format {%u %y%m%d} -gmt true -base 0]
} {0 0}
test clock-27.6 {yyddd over naked weekday} {
    list [clock scan {70001 1} -format {%y%j %u} -gmt true -base 0] \
	[clock scan {1 70001} -format {%u %y%j} -gmt true -base 0]
} {0 0}
test clock-27.7 {mmdd over naked weekday} {
    list [clock scan {0101 1} -format {%m%d %u} -gmt true -base 0] \
	[clock scan {1 0101} -format {%u %m%d} -gmt true -base 0]
} {0 0}
test clock-27.8 {ddd over naked weekday} {
    list [clock scan {001 1} -format {%j %u} -gmt true -base 0] \
	[clock scan {1 001} -format {%u %j} -gmt true -base 0]
} {0 0}
test clock-27.9 {naked day of month over naked weekday} {
    list [clock scan {01 1} -format {%d %u} -gmt true -base 0] \
	[clock scan {1 01} -format {%u %d} -gmt true -base 0]
} {0 0}


test clock-28.1 {base date} {
    clock scan {} -format {} -gmt true -base 1234567890
} 1234483200

# BEGIN testcases29








>
>
>
>
>
|


|
|


|
|


|
|


|
|


|
|


|
|


|
|


|
|


|
>







26421
26422
26423
26424
26425
26426
26427
26428
26429
26430
26431
26432
26433
26434
26435
26436
26437
26438
26439
26440
26441
26442
26443
26444
26445
26446
26447
26448
26449
26450
26451
26452
26453
26454
26455
26456
26457
26458
26459
26460
26461
26462
26463
26464
26465
26466
26467
26468
26469
26470
26471
26472
26473
26474
26475
26476
    clock scan vii -format %Ou -locale en_US_roman -gmt 1 -base 1009411200
} 1009670400
test clock-26.48 {parse naked day of week} {
    clock scan ? -format %Ow -locale en_US_roman -gmt 1 -base 1009411200
} 1009670400
# END testcases26

if {!$valid_mode} {
    set res {-result {0 0}}
} else {
    set res {-returnCodes error -result "unable to convert input string: invalid day of week"}
}
test clock-27.1 {seconds take precedence over naked weekday} -body {
    list [clock scan {0 1} -format {%s %u} -gmt true -base 0] \
	 [clock scan {1 0} -format {%u %s} -gmt true -base 0]
} {*}$res
test clock-27.2 {julian day takes precedence over naked weekday} -body {
    list [clock scan {2440588 1} -format {%J %u} -gmt true -base 0] \
	 [clock scan {1 2440588} -format {%u %J} -gmt true -base 0]
} {*}$res
test clock-27.3 {yyyymmdd over naked weekday} -body {
    list [clock scan {19700101 1} -format {%Y%m%d %u} -gmt true -base 0] \
	[clock scan {1 19700101} -format {%u %Y%m%d} -gmt true -base 0]
} {*}$res
test clock-27.4 {yyyyddd over naked weekday} -body {
    list [clock scan {1970001 1} -format {%Y%j %u} -gmt true -base 0] \
	[clock scan {1 1970001} -format {%u %Y%j} -gmt true -base 0]
} {*}$res
test clock-27.5 {yymmdd over naked weekday} -body {
    list [clock scan {700101 1} -format {%y%m%d %u} -gmt true -base 0] \
	[clock scan {1 700101} -format {%u %y%m%d} -gmt true -base 0]
} {*}$res
test clock-27.6 {yyddd over naked weekday} -body {
    list [clock scan {70001 1} -format {%y%j %u} -gmt true -base 0] \
	[clock scan {1 70001} -format {%u %y%j} -gmt true -base 0]
} {*}$res
test clock-27.7 {mmdd over naked weekday} -body {
    list [clock scan {0101 1} -format {%m%d %u} -gmt true -base 0] \
	[clock scan {1 0101} -format {%u %m%d} -gmt true -base 0]
} {*}$res
test clock-27.8 {ddd over naked weekday} -body {
    list [clock scan {001 1} -format {%j %u} -gmt true -base 0] \
	[clock scan {1 001} -format {%u %j} -gmt true -base 0]
} {*}$res
test clock-27.9 {naked day of month over naked weekday} -body {
    list [clock scan {01 1} -format {%d %u} -gmt true -base 0] \
	[clock scan {1 01} -format {%u %d} -gmt true -base 0]
} {*}$res
unset -nocomplain res

test clock-28.1 {base date} {
    clock scan {} -format {} -gmt true -base 1234567890
} 1234483200

# BEGIN testcases29

34965
34966
34967
34968
34969
34970
34971























34972
34973




34974
34975
34976
34977
34978
34979
34980
        -format {%J %Ol:%M:%S %P}
} 86399
test clock-29.1800 {time parsing} {
    clock scan {2440588 xi:lix:lix pm} \
        -gmt true -locale en_US_roman \
        -format {%J %Ol:%OM:%OS %P}
} 86399























# END testcases29





test clock-30.1 {clock add years} {
    set t [clock scan 2000-01-01 -format %Y-%m-%d -timezone :UTC]
    set f [clock add $t 1 year -timezone :UTC]
    clock format $f -format %Y-%m-%d -timezone :UTC
} {2001-01-01}
test clock-30.2 {clock add years - leap day} {
    set t [clock scan 2000-02-29 -format %Y-%m-%d -timezone :UTC]







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>







35472
35473
35474
35475
35476
35477
35478
35479
35480
35481
35482
35483
35484
35485
35486
35487
35488
35489
35490
35491
35492
35493
35494
35495
35496
35497
35498
35499
35500
35501
35502
35503
35504
35505
35506
35507
35508
35509
35510
35511
35512
35513
35514
        -format {%J %Ol:%M:%S %P}
} 86399
test clock-29.1800 {time parsing} {
    clock scan {2440588 xi:lix:lix pm} \
        -gmt true -locale en_US_roman \
        -format {%J %Ol:%OM:%OS %P}
} 86399

test clock-29.1811 {parsing of several localized formats} {
    set res {}
    foreach loc {en de fr} {
	foreach fmt {"%x %X" "%X %x"} {
	    lappend res [clock scan \
	      [clock format 0 -format $fmt -locale $loc -gmt 1] \
	      -format $fmt -locale $loc -gmt 1]
	}
    }
    set res
} [lrepeat 6 0]
test clock-29.1812 {parsing of several localized formats} {
    set res {}
    foreach loc {en de fr} {
	foreach fmt {"%a %d-%m-%Y" "%a %b %x-%X" "%a, %x %X" "%b, %x %X"} {
	    lappend res [clock scan \
	      [clock format 0 -format $fmt -locale $loc -gmt 1] \
	      -format $fmt -locale $loc -gmt 1]
	}
    }
    set res
} [lrepeat 12 0]
# END testcases29


# BEGIN testcases30

# Test [clock add]
test clock-30.1 {clock add years} {
    set t [clock scan 2000-01-01 -format %Y-%m-%d -timezone :UTC]
    set f [clock add $t 1 year -timezone :UTC]
    clock format $f -format %Y-%m-%d -timezone :UTC
} {2001-01-01}
test clock-30.2 {clock add years - leap day} {
    set t [clock scan 2000-02-29 -format %Y-%m-%d -timezone :UTC]
35211
35212
35213
35214
35215
35216
35217

























































































35218
35219
35220
35221
35222
35223
35224
    set t [clock scan {2004-10-31 01:00:00 -0400} \
	       -format {%Y-%m-%d %H:%M:%S %z} \
	       -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
    set f1 [clock add $t 3600 seconds -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
    set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
		-timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
} {2004-10-31 01:00:00 -0500}


























































































test clock-31.1 {system locale} \
    -constraints win \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







35745
35746
35747
35748
35749
35750
35751
35752
35753
35754
35755
35756
35757
35758
35759
35760
35761
35762
35763
35764
35765
35766
35767
35768
35769
35770
35771
35772
35773
35774
35775
35776
35777
35778
35779
35780
35781
35782
35783
35784
35785
35786
35787
35788
35789
35790
35791
35792
35793
35794
35795
35796
35797
35798
35799
35800
35801
35802
35803
35804
35805
35806
35807
35808
35809
35810
35811
35812
35813
35814
35815
35816
35817
35818
35819
35820
35821
35822
35823
35824
35825
35826
35827
35828
35829
35830
35831
35832
35833
35834
35835
35836
35837
35838
35839
35840
35841
35842
35843
35844
35845
35846
35847
    set t [clock scan {2004-10-31 01:00:00 -0400} \
	       -format {%Y-%m-%d %H:%M:%S %z} \
	       -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
    set f1 [clock add $t 3600 seconds -timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
    set x1 [clock format $f1 -format {%Y-%m-%d %H:%M:%S %z} \
		-timezone EST05:00EDT04:00,M4.1.0/02:00,M10.5.0/02:00]
} {2004-10-31 01:00:00 -0500}
test clock-30.26 {clock add weekdays} {
    set t [clock scan {2013-11-20}] ;# Wednesday
    set f1 [clock add $t 3 weekdays]
    set x1 [clock format $f1 -format {%Y-%m-%d}]
} {2013-11-25}
test clock-30.27 {clock add weekdays starting on Saturday} {
    set t [clock scan {2013-11-23}] ;# Saturday
    set f1 [clock add $t 1 weekday]
    set x1 [clock format $f1 -format {%Y-%m-%d}]
} {2013-11-25}
test clock-30.28 {clock add weekdays starting on Sunday} {
    set t [clock scan {2013-11-24}] ;# Sunday
    set f1 [clock add $t 1 weekday]
    set x1 [clock format $f1 -format {%Y-%m-%d}]
} {2013-11-25}
test clock-30.29 {clock add 0 weekdays starting on a weekend} {
    set t [clock scan {2016-02-27}] ;# Saturday
    set f1 [clock add $t 0 weekdays]
    set x1 [clock format $f1 -format {%Y-%m-%d}]
} {2016-02-27}
test clock-30.30 {clock add weekdays and back} -body {
    set n [clock seconds]
    # we start on each day of the week
    for {set i 0} {$i < 7} {incr i} {
        set start  [clock add $n $i days]
        set startu [clock format $start -format %u]
        # add 0 - 100 weekdays
        for {set j 0} {$j < 100} {incr j} {
            set forth [clock add $start $j weekdays]
            set back  [clock add $forth -$j weekdays]
            # If $s was a weekday or $j was 0, $b must be the same day.
            # Otherwise, $b must be the immediately preceeding Friday
            set fail 0
            if {$j == 0 || $startu < 6} {
                if {$start != $back} { set fail 1}
            } else {
                set friday [clock add $start -[expr {$startu % 5}] days]
                if {$friday != $back} { set fail 1 }
            }
            if {$fail} {
                set sdate [clock format $start -format {%Y-%m-%d}]
                set bdate [clock format $back  -format {%Y-%m-%d}]
                return "$sdate + $j - $j := $bdate"
            }
        }
    }
    return "OK"
} -result {OK}
test clock-30.31 {regression test - add no int overflow} {
    list \
      [list \
	[clock add 0 1600000000 seconds 24856 days -gmt 1] \
	[clock add 0 1600000000 seconds 815 months -gmt 1] \
	[clock add 0 1600000000 seconds 69 years -gmt 1] \
	[clock add 0 1600000000 seconds 596524 hours -gmt 1] \
	[clock add 0 1600000000 seconds 35791395 minutes -gmt 1] \
	[clock add 0 1600000000 seconds 0x7fffffff seconds -gmt 1]
      ] \
      [list \
	[clock add 1600000000 24856 days -gmt 1] \
	[clock add 1600000000 815 months -gmt 1] \
	[clock add 1600000000 69 years -gmt 1] \
	[clock add 1600000000 596524 hours -gmt 1] \
	[clock add 1600000000 35791395 minutes -gmt 1] \
	[clock add 1600000000 0x7fffffff seconds -gmt 1]
      ]
} [lrepeat 2 {3747558400 3743238400 3777452800 3747486400 3747483700 3747483647}]
test clock-30.32 {regression test - add no int overflow} {
    list \
      [list \
	[clock add 3777452800 -1600000000 seconds -24856 days -gmt 1] \
	[clock add 3777452800 -1600000000 seconds -815 months -gmt 1] \
	[clock add 3777452800 -1600000000 seconds -69 years -gmt 1] \
	[clock add 3777452800 -1600000000 seconds -596524 hours -gmt 1] \
	[clock add 3777452800 -1600000000 seconds -35791395 minutes -gmt 1] \
	[clock add 3777452800 -1600000000 seconds -0x7fffffff seconds -gmt 1]
      ] \
      [list \
	[clock add 2177452800 -24856 days -gmt 1] \
	[clock add 2177452800 -815 months -gmt 1] \
	[clock add 2177452800 -69 years -gmt 1] \
	[clock add 2177452800 -596524 hours -gmt 1] \
	[clock add 2177452800 -35791395 minutes -gmt 1] \
	[clock add 2177452800 -0x7fffffff seconds -gmt 1]
      ]
} [lrepeat 2 {29894400 34214400 0 29966400 29969100 29969153}]

# END testcases30


test clock-31.1 {system locale} \
    -constraints win \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
35432
35433
35434
35435
35436
35437
35438
35439
35440
35441
35442
35443
35444
35445
35446
35447
35448
35449
35450
35451
35452
35453
35454
35455
35456
35457
35458
35459
35460
35461
35462
35463
35464
35465
35466
35467
35468
35469
35470
35471
35472
35473
35474
35475
35476
35477
35478
35479
35480
35481
35482
35483
35484
35485
35486
35487
35488
35489
35490
35491
35492
35493
35494
35495
35496
    set problems
} {}

# Legacy tests

# clock clicks
test clock-33.1 {clock clicks tests} {
    expr [clock clicks]+1
    concat {}
} {}
test clock-33.2 {clock clicks tests} {
    set start [clock clicks]
    after 10
    set end [clock clicks]
    expr {$end > $start}
} {1}
test clock-33.3 {clock clicks tests} {
    list [catch {clock clicks foo} msg] $msg
} {1 {bad option "foo": must be -milliseconds or -microseconds}}
test clock-33.4 {clock clicks tests} {
    expr [clock clicks -milliseconds]+1
    concat {}
} {}
test clock-33.4a {clock milliseconds} {
    expr { [clock milliseconds] + 1 }
    concat {}
} {}
test clock-33.5 {clock clicks tests, millisecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.
    if {[lindex [timerate {
	set start [clock clicks -milli]
	timerate {} 10; # short but precise busy wait
	set end [clock clicks -milli]
    } 1 1] 0] > 60000} {
	::tcltest::Skip "timing issue"
    }
    # 60 msecs seems to be the max time slice under Windows 95/98
    expr {
	  ($end > $start) && (($end - $start) <= 60) ?
	  "ok" :
	  "test should have taken 0-60 ms, actually took [expr $end - $start]"}
} {ok}
test clock-33.5a {clock tests, millisecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.
    if {[lindex [timerate {
	set start [clock milliseconds]
	timerate {} 10; # short but precise busy wait
	set end [clock milliseconds]
    } 1 1] 0] > 60000} {
	::tcltest::Skip "timing issue"
    }
    # 60 msecs seems to be the max time slice under Windows 95/98
    expr {
	  ($end > $start) && (($end - $start) <= 60) ?
	  "ok" :
	  "test should have taken 0-60 ms, actually took [expr $end - $start]"}
} {ok}
test clock-33.6 {clock clicks, milli with too much abbreviation} {
    list [catch { clock clicks ? } msg] $msg
} {1 {bad option "?": must be -milliseconds or -microseconds}}
test clock-33.7 {clock clicks, milli with too much abbreviation} {
    list [catch { clock clicks - } msg] $msg
} {1 {ambiguous option "-": must be -milliseconds or -microseconds}}







|












|




















|















|







36055
36056
36057
36058
36059
36060
36061
36062
36063
36064
36065
36066
36067
36068
36069
36070
36071
36072
36073
36074
36075
36076
36077
36078
36079
36080
36081
36082
36083
36084
36085
36086
36087
36088
36089
36090
36091
36092
36093
36094
36095
36096
36097
36098
36099
36100
36101
36102
36103
36104
36105
36106
36107
36108
36109
36110
36111
36112
36113
36114
36115
36116
36117
36118
36119
    set problems
} {}

# Legacy tests

# clock clicks
test clock-33.1 {clock clicks tests} {
    expr {[clock clicks] + 1}
    concat {}
} {}
test clock-33.2 {clock clicks tests} {
    set start [clock clicks]
    after 10
    set end [clock clicks]
    expr {$end > $start}
} {1}
test clock-33.3 {clock clicks tests} {
    list [catch {clock clicks foo} msg] $msg
} {1 {bad option "foo": must be -milliseconds or -microseconds}}
test clock-33.4 {clock clicks tests} {
    expr {[clock clicks -milliseconds] + 1}
    concat {}
} {}
test clock-33.4a {clock milliseconds} {
    expr { [clock milliseconds] + 1 }
    concat {}
} {}
test clock-33.5 {clock clicks tests, millisecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.
    if {[lindex [timerate {
	set start [clock clicks -milli]
	timerate {} 10; # short but precise busy wait
	set end [clock clicks -milli]
    } 1 1] 0] > 60000} {
	::tcltest::Skip "timing issue"
    }
    # 60 msecs seems to be the max time slice under Windows 95/98
    expr {
	  ($end > $start) && (($end - $start) <= 60) ?
	  "ok" :
	  "test should have taken 0-60 ms, actually took [expr {$end - $start}]"}
} {ok}
test clock-33.5a {clock tests, millisecond timing test} {
    # This test can fail on a system that is so heavily loaded that
    # the test takes >60 ms to run.
    if {[lindex [timerate {
	set start [clock milliseconds]
	timerate {} 10; # short but precise busy wait
	set end [clock milliseconds]
    } 1 1] 0] > 60000} {
	::tcltest::Skip "timing issue"
    }
    # 60 msecs seems to be the max time slice under Windows 95/98
    expr {
	  ($end > $start) && (($end - $start) <= 60) ?
	  "ok" :
	  "test should have taken 0-60 ms, actually took [expr {$end - $start}]"}
} {ok}
test clock-33.6 {clock clicks, milli with too much abbreviation} {
    list [catch { clock clicks ? } msg] $msg
} {1 {bad option "?": must be -milliseconds or -microseconds}}
test clock-33.7 {clock clicks, milli with too much abbreviation} {
    list [catch { clock clicks - } msg] $msg
} {1 {ambiguous option "-": must be -milliseconds or -microseconds}}
35580
35581
35582
35583
35584
35585
35586

35587
35588
35589
35590
35591
35592
35593
35594
35595
35596
	if { $t3 == $t1 } break
	set t1 $t3
    }
    expr { $t2 / 1000 == $t3 }
} {1}

# clock scan

test clock-34.1 {clock scan tests} {
    list [catch {clock scan} msg] $msg
} {1 {wrong # args: should be "clock scan string ?-base seconds? ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE?"}}
test clock-34.2 {clock scan tests} {*}{
    -body {clock scan "bad-string"}
    -returnCodes error
    -match glob
    -result {unable to convert date-time string "bad-string"*}
}
test clock-34.3 {clock scan tests} {







>


|







36203
36204
36205
36206
36207
36208
36209
36210
36211
36212
36213
36214
36215
36216
36217
36218
36219
36220
	if { $t3 == $t1 } break
	set t1 $t3
    }
    expr { $t2 / 1000 == $t3 }
} {1}

# clock scan
set syntax "clock scan string ?-base seconds? ?-format string? ?-gmt boolean? ?-locale LOCALE? ?-timezone ZONE? ?-validate boolean?"
test clock-34.1 {clock scan tests} {
    list [catch {clock scan} msg] $msg
} [subst {1 {wrong # args: should be "$syntax"}}]
test clock-34.2 {clock scan tests} {*}{
    -body {clock scan "bad-string"}
    -returnCodes error
    -match glob
    -result {unable to convert date-time string "bad-string"*}
}
test clock-34.3 {clock scan tests} {
35616
35617
35618
35619
35620
35621
35622
35623
35624
35625
35626
35627
35628
35629
35630
35631
35632









35633
35634
35635
35636

35637
35638
35639
35640
35641
35642
35643
35644
35645
35646
35647
35648
35649
35650
35651












35652
35653
35654
35655
35656





























35657
35658
35659
35660






















































































































35661
35662
35663
35664
35665
35666
35667
} {Oct 23,1992 15:00 GMT}
test clock-34.8 {clock scan tests} {
    set time [clock scan "Oct 23,1992 15:00" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Oct 23,1992 15:00 GMT}
test clock-34.9 {clock scan tests} {
    list [catch {clock scan "Jan 12" -bad arg} msg] $msg
} {1 {bad option "-bad", must be -base, -format, -gmt, -locale or -timezone}}
# The following two two tests test the two year date policy
test clock-34.10 {clock scan tests} {
    set time [clock scan "1/1/71" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,1971 00:00 GMT}
test clock-34.11 {clock scan tests} {
    set time [clock scan "1/1/37" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,2037 00:00 GMT}









test clock-34.12 {clock scan, relative times} {
    set time [clock scan "Oct 23, 1992 -1 day"]
    clock format $time -format {%b %d, %Y}
} "Oct 22, 1992"

test clock-34.13 {clock scan, ISO 8601 base date format} {
    set time [clock scan "19921023"]
    clock format $time -format {%b %d, %Y}
} "Oct 23, 1992"
test clock-34.14 {clock scan, ISO 8601 expanded date format} {
    set time [clock scan "1992-10-23"]
    clock format $time -format {%b %d, %Y}
} "Oct 23, 1992"
test clock-34.15 {clock scan, DD-Mon-YYYY format} {
    set time [clock scan "23-Oct-1992"]
    clock format $time -format {%b %d, %Y}
} "Oct 23, 1992"
test clock-34.16 {clock scan, ISO 8601 point in time format} {
    set time [clock scan "19921023T235959"]
    clock format $time -format {%b %d, %Y %H:%M:%S}












} "Oct 23, 1992 23:59:59"
test clock-34.17 {clock scan, ISO 8601 point in time format} {
    set time [clock scan "19921023 235959"]
    clock format $time -format {%b %d, %Y %H:%M:%S}
} "Oct 23, 1992 23:59:59"





























test clock-34.18 {clock scan, ISO 8601 point in time format} {
    set time [clock scan "19921023T000000"]
    clock format $time -format {%b %d, %Y %H:%M:%S}
} "Oct 23, 1992 00:00:00"























































































































# CLOCK SCAN REAL TESTS
# We use 5am PST, 31-12-1999 as the base for these scans because irrespective
# of your local timezone it should always give us times on December 31, 1999
set 5amPST 946645200
test clock-34.19 {clock scan, number meridian} {
    set t1 [clock scan "5 am" -base $5amPST -gmt true]







|









>
>
>
>
>
>
>
>
>

|
|

>

|
|


|
|


|
|


|
|
>
>
>
>
>
>
>
>
>
>
>
>


|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







36240
36241
36242
36243
36244
36245
36246
36247
36248
36249
36250
36251
36252
36253
36254
36255
36256
36257
36258
36259
36260
36261
36262
36263
36264
36265
36266
36267
36268
36269
36270
36271
36272
36273
36274
36275
36276
36277
36278
36279
36280
36281
36282
36283
36284
36285
36286
36287
36288
36289
36290
36291
36292
36293
36294
36295
36296
36297
36298
36299
36300
36301
36302
36303
36304
36305
36306
36307
36308
36309
36310
36311
36312
36313
36314
36315
36316
36317
36318
36319
36320
36321
36322
36323
36324
36325
36326
36327
36328
36329
36330
36331
36332
36333
36334
36335
36336
36337
36338
36339
36340
36341
36342
36343
36344
36345
36346
36347
36348
36349
36350
36351
36352
36353
36354
36355
36356
36357
36358
36359
36360
36361
36362
36363
36364
36365
36366
36367
36368
36369
36370
36371
36372
36373
36374
36375
36376
36377
36378
36379
36380
36381
36382
36383
36384
36385
36386
36387
36388
36389
36390
36391
36392
36393
36394
36395
36396
36397
36398
36399
36400
36401
36402
36403
36404
36405
36406
36407
36408
36409
36410
36411
36412
36413
36414
36415
36416
36417
36418
36419
36420
36421
36422
36423
36424
36425
36426
36427
36428
36429
36430
36431
36432
36433
36434
36435
36436
36437
36438
36439
36440
36441
36442
36443
36444
36445
36446
36447
36448
36449
36450
36451
36452
36453
36454
36455
36456
36457
36458
36459
36460
} {Oct 23,1992 15:00 GMT}
test clock-34.8 {clock scan tests} {
    set time [clock scan "Oct 23,1992 15:00" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Oct 23,1992 15:00 GMT}
test clock-34.9 {clock scan tests} {
    list [catch {clock scan "Jan 12" -bad arg} msg] $msg
} [subst {1 {bad option "-bad": must be -base, -format, -gmt, -locale, -timezone or -validate}}]
# The following two two tests test the two year date policy
test clock-34.10 {clock scan tests} {
    set time [clock scan "1/1/71" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,1971 00:00 GMT}
test clock-34.11 {clock scan tests} {
    set time [clock scan "1/1/37" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M GMT} -gmt true
} {Jan 01,2037 00:00 GMT}
test clock-34.11.1 {clock scan tests: same century switch} {
    set times [clock scan "1/1/37" -gmt true]
} [clock scan "1/1/37" -format "%m/%d/%y" -gmt true]
test clock-34.11.2 {clock scan tests: same century switch} {
    set times [clock scan "1/1/38" -gmt true]
} [clock scan "1/1/38" -format "%m/%d/%y" -gmt true]
test clock-34.11.3 {clock scan tests: same century switch} {
    set times [clock scan "1/1/39" -gmt true]
} [clock scan "1/1/39" -format "%m/%d/%y" -gmt true]
test clock-34.12 {clock scan, relative times} {
    set time [clock scan "Oct 23, 1992 -1 day"  -gmt true]
    clock format $time -format {%b %d, %Y} -gmt true
} "Oct 22, 1992"

test clock-34.13 {clock scan, ISO 8601 base date format} {
    set time [clock scan "19921023" -gmt true]
    clock format $time -format {%b %d, %Y} -gmt true
} "Oct 23, 1992"
test clock-34.14 {clock scan, ISO 8601 expanded date format} {
    set time [clock scan "1992-10-23" -gmt true]
    clock format $time -format {%b %d, %Y} -gmt true
} "Oct 23, 1992"
test clock-34.15 {clock scan, DD-Mon-YYYY format} {
    set time [clock scan "23-Oct-1992" -gmt true]
    clock format $time -format {%b %d, %Y} -gmt true
} "Oct 23, 1992"
test clock-34.16 {clock scan, ISO 8601 point in time format} {
    set time [clock scan "19921023T235959" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.16.1a {clock scan, ISO 8601 T literal optional (YYYYMMDDhhmmss)} {
    set time [clock scan "19921023235959" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.16.1b {clock scan, ISO 8601 T literal optional (YYYYMMDDhhmm)} {
    set time [clock scan "199210232359" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:00"
test clock-34.16.2 {clock scan, ISO 8601 extended date time} {
    set time [clock scan "1992-10-23T23:59:59" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17 {clock scan, ISO 8601 point in time format} {
    set time [clock scan "19921023 235959" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17.2a {clock scan, ISO 8601 extended date time (YYYY-MM-DD hh:mm:ss)} {
    set time [clock scan "1992-10-23 23:59:59" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17.2b {clock scan, ISO 8601 extended date time (YYYY-MM-DDThh:mm:ss)} {
    set time [clock scan "1992-10-23T23:59:59" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17.2c {clock scan, ISO 8601 extended date time (YYYY-MM-DD hh:mm)} {
    set time [clock scan "1992-10-23 23:59" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:00"
test clock-34.17.2d {clock scan, ISO 8601 extended date time (YYYY-MM-DDThh:mm)} {
    set time [clock scan "1992-10-23T23:59" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:00"
test clock-34.17.3 {clock scan, TZ-word boundaries - Z is not TZ here } -body {
    set time [clock scan "1992-10-23Z23:59:59" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} -returnCodes error -match glob \
  -result {unable to convert date-time string*}
test clock-34.17.4 {clock scan, TZ-word boundaries - Z is TZ UTC here} {
    set time [clock scan "1992-10-23 Z 23:59:59" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.17.5 {clock scan, ISO 8601 extended date time with UTC TZ} {
    set time [clock scan "1992-10-23T23:59:59Z" -timezone :America/Detroit]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 23:59:59"
test clock-34.18 {clock scan, ISO 8601 point in time format} {
    set time [clock scan "19921023T000000" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 00:00:00"
test clock-34.18.2 {clock scan, ISO 8601 extended date time} {
    set time [clock scan "1992-10-23T00:00:00" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 00:00:00"
test clock-34.18.3 {clock scan, TZ-word boundaries - Z is not TZ here } -body {
    set time [clock scan "1992-10-23Z00:00:00" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} -returnCodes error -match glob \
  -result {unable to convert date-time string*}
test clock-34.18.4 {clock scan, TZ-word boundaries - Z is TZ UTC here} {
    set time [clock scan "1992-10-23 Z 00:00:00" -gmt true]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 00:00:00"
test clock-34.18.5 {clock scan, ISO 8601 extended date time with UTC TZ} {
    set time [clock scan "1992-10-23T00:00:00Z" -timezone :America/Detroit]
    clock format $time -format {%b %d, %Y %H:%M:%S} -gmt true
} "Oct 23, 1992 00:00:00"

test clock-34.20.1 {clock scan tests (-TZ)} {
    set time [clock scan "31 Jan 14 23:59:59 -0100" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Feb 01,2014 00:59:59 GMT}
test clock-34.20.2 {clock scan tests (+TZ)} {
    set time [clock scan "31 Jan 14 23:59:59 +0100" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 31,2014 22:59:59 GMT}
test clock-34.20.3 {clock scan tests (-TZ)} {
    set time [clock scan "23:59:59 -0100" -base 0 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 02,1970 00:59:59 GMT}
test clock-34.20.4 {clock scan tests (+TZ)} {
    set time [clock scan "23:59:59 +0100" -base 0 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 01,1970 22:59:59 GMT}
test clock-34.20.5 {clock scan tests (TZ)} {
    set time [clock scan "Mon, 30 Jun 2014 23:59:59 CEST" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jun 30,2014 21:59:59 GMT}
test clock-34.20.6 {clock scan tests (TZ)} {
    set time [clock scan "Fri, 31 Jan 2014 23:59:59 CET" -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 31,2014 22:59:59 GMT}
test clock-34.20.7 {clock scan tests (relspec, day unit not TZ)} {
    set time [clock scan "23:59:59 +15 day" -base 2000000 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Feb 08,1970 23:59:59 GMT}
test clock-34.20.8 {clock scan tests (relspec, day unit not TZ)} {
    set time [clock scan "23:59:59 -15 day" -base 2000000 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 09,1970 23:59:59 GMT}
test clock-34.20.9 {clock scan tests (merid and TZ)} {
    set time [clock scan "10:59 pm CET" -base 2000000 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
test clock-34.20.10 {clock scan tests (merid and TZ)} {
    set time [clock scan "10:59 pm +0100" -base 2000000 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
test clock-34.20.11 {clock scan tests (complex TZ)} {
    list [clock scan "GMT+1000" -base 100000000 -gmt 1] \
	 [clock scan "GMT+10" -base 100000000 -gmt 1] \
	 [clock scan "+1000" -base 100000000 -gmt 1]
} [lrepeat 3 99964000]
test clock-34.20.12 {clock scan tests (complex TZ)} {
    list [clock scan "GMT-1000" -base 100000000 -gmt 1] \
	 [clock scan "GMT-10" -base 100000000 -gmt 1] \
	 [clock scan "-1000" -base 100000000 -gmt 1]
} [lrepeat 3 100036000]
test clock-34.20.13 {clock scan tests (complex TZ)} {
    list [clock scan "GMT-0000" -base 100000000 -gmt 1] \
	 [clock scan "GMT+0000" -base 100000000 -gmt 1] \
	 [clock scan "GMT" -base 100000000 -gmt 1]
} [lrepeat 3 100000000]
test clock-34.20.14 {clock scan tests (complex TZ)} {
    list [clock scan "CET+1000" -base 100000000 -gmt 1] \
	 [clock scan "CET-1000" -base 100000000 -gmt 1]
} {99960400 100032400}
test clock-34.20.15 {clock scan tests (complex TZ)} {
    list [clock scan "CET-0000" -base 100000000 -gmt 1] \
	 [clock scan "CET+0000" -base 100000000 -gmt 1] \
	 [clock scan "CET" -base 100000000 -gmt 1]
} [lrepeat 3 99996400]
test clock-34.20.16 {clock scan tests (complex TZ)} {
    list [clock format [clock scan "00:00 GMT+1000" -base 100000000 -gmt 1] -gmt 1] \
	 [clock format [clock scan "00:00 GMT+10" -base 100000000 -gmt 1] -gmt 1] \
	 [clock format [clock scan "00:00 +1000" -base 100000000 -gmt 1] -gmt 1] \
	 [clock format [clock scan "00:00" -base 100000000 -timezone +1000] -gmt 1]
} [lrepeat 4 "Fri Mar 02 14:00:00 GMT 1973"]
test clock-34.20.17 {clock scan tests (complex TZ)} {
    list [clock format [clock scan "00:00 GMT+0100" -base 100000000 -gmt 1] -gmt 1] \
	 [clock format [clock scan "00:00 GMT+01" -base 100000000 -gmt 1] -gmt 1] \
	 [clock format [clock scan "00:00 GMT+1" -base 100000000 -gmt 1] -gmt 1] \
	 [clock format [clock scan "00:00" -base 100000000 -timezone +0100] -gmt 1]
} [lrepeat 4 "Fri Mar 02 23:00:00 GMT 1973"]
test clock-34.20.18 {clock scan tests (no TZ)} {
    list [clock scan "1000days" -base 100000000 -gmt 1] \
	 [clock scan "1000 days" -base 100000000 -gmt 1] \
	 [clock scan "+1000days" -base 100000000 -gmt 1] \
	 [clock scan "+1000 days" -base 100000000 -gmt 1] \
	 [clock scan "GMT +1000 days" -base 100000000 -gmt 1] \
	 [clock scan "00:00 GMT +1000 days" -base 100000000 -gmt 1]
} [lrepeat 6 186364800]
test clock-34.20.19 {clock scan tests (no TZ)} {
    list [clock scan "-1000days" -base 100000000 -gmt 1] \
	 [clock scan "-1000 days" -base 100000000 -gmt 1] \
	 [clock scan "GMT -1000days" -base 100000000 -gmt 1] \
	 [clock scan "00:00 GMT -1000 days" -base 100000000 -gmt 1] \
} [lrepeat 4 13564800]
test clock-34.20.20 {clock scan tests (TZ, TZ + 1day)} {
    clock scan "00:00 GMT+1000 day" -base 100000000 -gmt 1
} 100015200
test clock-34.20.21 {clock scan tests (local date of base depends on given TZ, time apllied to different day)} {
    list [clock scan "23:59:59 -0100" -base 0 -timezone :CET] \
	 [clock scan "23:59:59 -0100" -base 0 -gmt 1] \
	 [clock scan "23:59:59 -0100" -base 0 -timezone -1400] \
	 [clock scan "23:59:59 -0100" -base 0 -timezone :Pacific/Apia]
} {89999 89999 3599 3599}


# CLOCK SCAN REAL TESTS
# We use 5am PST, 31-12-1999 as the base for these scans because irrespective
# of your local timezone it should always give us times on December 31, 1999
set 5amPST 946645200
test clock-34.19 {clock scan, number meridian} {
    set t1 [clock scan "5 am" -base $5amPST -gmt true]
35748
35749
35750
35751
35752
35753
35754





















35755
35756
35757
35758
35759
35760
35761
    clock format [clock scan "thursday" -base [clock scan 20000112]] \
	    -format {%b %d, %Y}
} "Jan 13, 2000"
test clock-34.40 {clock scan, next day of week} {
    clock format [clock scan "next thursday" -base [clock scan 20000112]] \
	    -format {%b %d, %Y}
} "Jan 20, 2000"






















# weekday specification and base.
test clock-34.41 {2nd monday in november} {
    set res {}
    foreach i {91 92 93 94 95 96} {
      set nov8th [clock scan 11/8/$i]
      set monday [clock scan monday -base $nov8th]







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







36541
36542
36543
36544
36545
36546
36547
36548
36549
36550
36551
36552
36553
36554
36555
36556
36557
36558
36559
36560
36561
36562
36563
36564
36565
36566
36567
36568
36569
36570
36571
36572
36573
36574
36575
    clock format [clock scan "thursday" -base [clock scan 20000112]] \
	    -format {%b %d, %Y}
} "Jan 13, 2000"
test clock-34.40 {clock scan, next day of week} {
    clock format [clock scan "next thursday" -base [clock scan 20000112]] \
	    -format {%b %d, %Y}
} "Jan 20, 2000"
test clock-34.40.1 {clock scan, ordinal month after relative date} {
    # This will fail without the bug fix (clock.tcl), as still missing
    # month/julian day conversion before ordinal month increment
    clock format [ \
        clock scan "5 years 18 months 387 days" -base 0 -gmt 1
    ] -format {%a, %b %d, %Y} -gmt 1 -locale en_US_roman
} "Sat, Jul 23, 1977"
test clock-34.40.2 {clock scan, ordinal month after relative date} {
    # This will fail without the bug fix (clock.tcl), as still missing
    # month/julian day conversion before ordinal month increment
    clock format [ \
        clock scan "5 years 18 months 387 days next Jan" -base 0 -gmt 1
    ] -format {%a, %b %d, %Y} -gmt 1 -locale en_US_roman
} "Mon, Jan 23, 1978"
test clock-34.40.3 {clock scan, day of week after ordinal date} {
    # This will fail without the bug fix (clock.tcl), because the relative
    # week day should be applied after whole date conversion
    clock format [ \
        clock scan "5 years 18 months 387 days next January Fri" -base 0 -gmt 1
    ] -format {%a, %b %d, %Y} -gmt 1 -locale en_US_roman
} "Fri, Jan 27, 1978"

# weekday specification and base.
test clock-34.41 {2nd monday in november} {
    set res {}
    foreach i {91 92 93 94 95 96} {
      set nov8th [clock scan 11/8/$i]
      set monday [clock scan monday -base $nov8th]
35898
35899
35900
35901
35902
35903
35904
35905
























































































35906
35907
35908
35909
35910
35911
35912
35913
35914
35915
    set time [clock scan "10:59 pm CET" -base 2000000 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
test clock-34.68 {clock scan tests (merid and TZ)} {
    set time [clock scan "10:59 pm +0100" -base 2000000 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}

























































































# clock seconds
test clock-35.1 {clock seconds tests} {
    expr [clock seconds]+1
    concat {}
} {}
test clock-35.2 {clock seconds tests} {
    list [catch {clock seconds foo} msg] $msg
} {1 {wrong # args: should be "clock seconds"}}
test clock-35.3 {clock seconds tests} {
    set start [clock seconds]








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|







36712
36713
36714
36715
36716
36717
36718
36719
36720
36721
36722
36723
36724
36725
36726
36727
36728
36729
36730
36731
36732
36733
36734
36735
36736
36737
36738
36739
36740
36741
36742
36743
36744
36745
36746
36747
36748
36749
36750
36751
36752
36753
36754
36755
36756
36757
36758
36759
36760
36761
36762
36763
36764
36765
36766
36767
36768
36769
36770
36771
36772
36773
36774
36775
36776
36777
36778
36779
36780
36781
36782
36783
36784
36785
36786
36787
36788
36789
36790
36791
36792
36793
36794
36795
36796
36797
36798
36799
36800
36801
36802
36803
36804
36805
36806
36807
36808
36809
36810
36811
36812
36813
36814
36815
36816
36817
    set time [clock scan "10:59 pm CET" -base 2000000 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}
test clock-34.68 {clock scan tests (merid and TZ)} {
    set time [clock scan "10:59 pm +0100" -base 2000000 -gmt true]
    clock format $time -format {%b %d,%Y %H:%M:%S %Z} -gmt true
} {Jan 24,1970 21:59:00 GMT}

test clock-34.69.1 {relative from base, date switch} {
    set base [clock scan "12/31/2016 23:59:59" -gmt 1]
    clock format [clock scan "+1 second" \
       -base $base -gmt 1] -gmt 1 -format {%Y-%m-%d %H:%M:%S}
} {2017-01-01 00:00:00}
test clock-34.69.2 {relative time, daylight switch} {
    set base [clock scan "03/27/2016" -timezone CET]
    set res {}
    lappend res [clock format [clock scan "+1 hour" \
       -base $base -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
    lappend res [clock format [clock scan "+2 hour" \
       -base $base -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
} {{2016-03-27 01:00:00 CET} {2016-03-27 03:00:00 CEST}}

test clock-34.69.3 {relative time with day increment / daylight switch} {
    set base [clock scan "03/27/2016" -timezone CET]
    set res {}
    lappend res [clock format [clock scan "+5 day +25 hour" \
       -base [expr {$base - 6*24*60*60}] -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
    lappend res [clock format [clock scan "+5 day +26 hour" \
       -base [expr {$base - 6*24*60*60}] -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
} {{2016-03-27 01:00:00 CET} {2016-03-27 03:00:00 CEST}}

test clock-34.69.4 {relative time with month & day increment / daylight switch} {
    set base [clock scan "03/27/2016" -timezone CET]
    set res {}
    lappend res [clock format [clock scan "next Mar +5 day +25 hour" \
       -base [expr {$base - 35*24*60*60}] -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
    lappend res [clock format [clock scan "next Mar +5 day +26 hour" \
       -base [expr {$base - 35*24*60*60}] -timezone CET] -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]
} {{2016-03-27 01:00:00 CET} {2016-03-27 03:00:00 CEST}}

test clock-34.70.1 {check date in DST-hole: daylight switch CET -> CEST} {
    set res {}
    # forwards
    set base 1459033200
    for {set i 0} {$i <= 3} {incr i} {
    	set d [clock scan "+$i hour" -base $base -timezone CET]
    	lappend res "$d = [clock format $d -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]"
    }
    lappend res "#--"
    # backwards
    set base 1459044000
    for {set i 0} {$i <= 3} {incr i} {
    	set d [clock scan "-$i hour" -base $base -timezone CET]
    	lappend res "$d = [clock format $d -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]"
    }
    set res
} [split [regsub -all {^\n|\n$} {
1459033200 = 2016-03-27 00:00:00 CET
1459036800 = 2016-03-27 01:00:00 CET
1459040400 = 2016-03-27 03:00:00 CEST
1459044000 = 2016-03-27 04:00:00 CEST
#--
1459044000 = 2016-03-27 04:00:00 CEST
1459040400 = 2016-03-27 03:00:00 CEST
1459036800 = 2016-03-27 01:00:00 CET
1459033200 = 2016-03-27 00:00:00 CET
} {}] \n]

test clock-34.70.2 {check date in DST-hole: daylight switch CEST -> CET} {
    set res {}
    # forwards
    set base 1477782000
    for {set i 0} {$i <= 3} {incr i} {
    	set d [clock scan "+$i hour" -base $base -timezone CET]
    	lappend res "$d = [clock format $d -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]"
    }
    lappend res "#--"
    # backwards
    set base 1477792800
    for {set i 0} {$i <= 3} {incr i} {
    	set d [clock scan "-$i hour" -base $base -timezone CET]
    	lappend res "$d = [clock format $d -timezone CET -format {%Y-%m-%d %H:%M:%S %Z}]"
    }
    set res
} [split [regsub -all {^\n|\n$} {
1477782000 = 2016-10-30 01:00:00 CEST
1477785600 = 2016-10-30 02:00:00 CEST
1477789200 = 2016-10-30 02:00:00 CET
1477792800 = 2016-10-30 03:00:00 CET
#--
1477792800 = 2016-10-30 03:00:00 CET
1477789200 = 2016-10-30 02:00:00 CET
1477785600 = 2016-10-30 02:00:00 CEST
1477782000 = 2016-10-30 01:00:00 CEST
} {}] \n]

# clock seconds
test clock-35.1 {clock seconds tests} {
    expr {[clock seconds] + 1}
    concat {}
} {}
test clock-35.2 {clock seconds tests} {
    list [catch {clock seconds foo} msg] $msg
} {1 {wrong # args: should be "clock seconds"}}
test clock-35.3 {clock seconds tests} {
    set start [clock seconds]
35929
35930
35931
35932
35933
35934
35935
35936
35937
35938


35939
35940
35941
35942


















35943
35944
35945
35946
35947
35948
35949
} "07.2000"
test clock-36.3 {clock scan next monthname} {
    clock format [clock scan "next may" -base [clock scan "june 1, 2000"]] \
	    -format %m.%Y
} "05.2001"

test clock-37.1 {%s gmt testing} {
    set s [clock seconds]
    set a [clock format $s -format %s -gmt 0]
    set b [clock format $s -format %s -gmt 1]


    # %s, being the difference between local and Greenwich, does not
    # depend on the time zone.
    set c [expr {$b-$a}]
} {0}



















test clock-38.1 {regression - convertUTCToLocalViaC - east of Greenwich} \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
	set env(TZ) CET-01:00CEST-02:00,M3.5.0/02:00,M10.5.0/03:00







|


>
>


|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







36831
36832
36833
36834
36835
36836
36837
36838
36839
36840
36841
36842
36843
36844
36845
36846
36847
36848
36849
36850
36851
36852
36853
36854
36855
36856
36857
36858
36859
36860
36861
36862
36863
36864
36865
36866
36867
36868
36869
36870
36871
} "07.2000"
test clock-36.3 {clock scan next monthname} {
    clock format [clock scan "next may" -base [clock scan "june 1, 2000"]] \
	    -format %m.%Y
} "05.2001"

test clock-37.1 {%s gmt testing} {
    set s [clock scan "2017-05-10 09:00:00" -gmt 1]
    set a [clock format $s -format %s -gmt 0]
    set b [clock format $s -format %s -gmt 1]
    set c [clock scan $s -format %s -gmt 0]
    set d [clock scan $s -format %s -gmt 1]
    # %s, being the difference between local and Greenwich, does not
    # depend on the time zone.
    list [expr {$b-$a}] [expr {$d-$c}]
} {0 0}
test clock-37.2 {%Es gmt testing CET} {
    set s [clock scan "2017-01-10 09:00:00" -gmt 1]
    set a [clock format $s -format %Es -timezone CET]
    set b [clock format $s -format %Es -gmt 1]
    set c [clock scan $s -format %Es -timezone CET]
    set d [clock scan $s -format %Es -gmt 1]
    # %Es depend on the time zone (local seconds instead of posix seconds).
    list [expr {$b-$a}] [expr {$d-$c}]
} {-3600 3600}
test clock-37.3 {%Es gmt testing CEST} {
    set s [clock scan "2017-05-10 09:00:00" -gmt 1]
    set a [clock format $s -format %Es -timezone CET]
    set b [clock format $s -format %Es -gmt 1]
    set c [clock scan $s -format %Es -timezone CET]
    set d [clock scan $s -format %Es -gmt 1]
    # %Es depend on the time zone (local seconds instead of posix seconds).
    list [expr {$b-$a}] [expr {$d-$c}]
} {-7200 7200}

test clock-38.1 {regression - convertUTCToLocalViaC - east of Greenwich} \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
	set env(TZ) CET-01:00CEST-02:00,M3.5.0/02:00,M10.5.0/03:00
35989
35990
35991
35992
35993
35994
35995














































35996
35997
35998
35999
36000
36001
36002
        if { [info exists oldTclTZ] } {
            set env(TCL_TZ) $oldTclTZ
            unset oldTclTZ
        }
    } \
    -result 1
















































test clock-39.1 {regression - synonym timezones} {
    clock format 0 -format {%H:%M:%S} -timezone :US/Eastern
} {19:00:00}

test clock-40.1 {regression - bad month with -timezone :localtime} \
    -setup {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







36911
36912
36913
36914
36915
36916
36917
36918
36919
36920
36921
36922
36923
36924
36925
36926
36927
36928
36929
36930
36931
36932
36933
36934
36935
36936
36937
36938
36939
36940
36941
36942
36943
36944
36945
36946
36947
36948
36949
36950
36951
36952
36953
36954
36955
36956
36957
36958
36959
36960
36961
36962
36963
36964
36965
36966
36967
36968
36969
36970
        if { [info exists oldTclTZ] } {
            set env(TCL_TZ) $oldTclTZ
            unset oldTclTZ
        }
    } \
    -result 1

test clock-38.3sc {ensure cache of base is correct for :localtime if TZ-env changing / scan} \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
    } \
    -body {
	set res {}
	foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} \
	        i {{07:30:00} {03:30:00} {23:30:00} {20:00:00}} \
	{
	    lappend res [clock scan $i -format "%H:%M:%S" -base [expr {20*60*60}] -timezone :localtime]
	}
	set res
    } \
    -cleanup {
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result [lrepeat 4 [expr {20*60*60}]]
test clock-38.3fm {ensure cache of base is correct for :localtime if TZ-env changing / format} \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
    } \
    -body {
	set res {}
	foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} {
	    lappend res [clock format [expr {20*60*60}] -format "%Y-%m-%dT%H:%M:%S %Z" -timezone :localtime]
	}
	set res
    } \
    -cleanup {
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result {{1970-01-02T07:30:00 +1130} {1970-01-02T03:30:00 +0730} {1970-01-01T23:30:00 +0330} {1970-01-01T20:00:00 +0000}}

test clock-39.1 {regression - synonym timezones} {
    clock format 0 -format {%H:%M:%S} -timezone :US/Eastern
} {19:00:00}

test clock-40.1 {regression - bad month with -timezone :localtime} \
    -setup {
36039
36040
36041
36042
36043
36044
36045
36046
36047
36048
36049
36050
36051
36052
36053
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result {-0500}

# 43.1 was a bad test - mktime returning -1 is an error according to posix.

test clock-44.1 {regression test - time zone name containing hyphen } \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
	set env(TZ) US/East-Indiana







|







37007
37008
37009
37010
37011
37012
37013
37014
37015
37016
37017
37018
37019
37020
37021
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result {-0500}

# 43.1 was a bad test - mktime returning -1 is an error according to Posix.

test clock-44.1 {regression test - time zone name containing hyphen } \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
	set env(TZ) US/East-Indiana
36061
36062
36063
36064
36065
36066
36067
36068
36069
36070
36071
36072
36073













































































36074
36075
36076
36077
36078
36079
36080
36081
36082
36083
36084
36085
36086
36087
36088
36089



































































































































































































































36090
36091
36092
36093
36094
36095
36096
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result {12:34:56-0500}

test clock-45.1 {regression test - time zone containing only two digits} \
    -body {
	clock scan 1985-04-12T10:15:30+04 -format %Y-%m-%dT%H:%M:%S%Z
    } \
    -result 482134530














































































test clock-46.1 {regression test - month zero} \
    -body {
	clock scan 2004-00-00 -format %Y-%m-%d
    } -result [clock scan 2003-11-30 -format %Y-%m-%d]
test clock-46.2 {regression test - month zero} \
    -body {
	clock scan 20040000
    } -result [clock scan 2003-11-30 -format %Y-%m-%d]
test clock-46.3 {regression test - month thirteen} \
    -body {
	clock scan 2004-13-01 -format %Y-%m-%d
    } -result [clock scan 2005-01-01 -format %Y-%m-%d]
test clock-46.4 {regression test - month thirteen} \
    -body {
	clock scan 20041301
    } -result [clock scan 2005-01-01 -format %Y-%m-%d]




































































































































































































































test clock-47.1 {regression test - four-digit time} {
    clock scan 0012
} [clock scan 0012 -format %H%M]
test clock-47.2 {regression test - four digit time} {
    clock scan 0039
} [clock scan 0039 -format %H%M]







|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|



|



|



|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







37029
37030
37031
37032
37033
37034
37035
37036
37037
37038
37039
37040
37041
37042
37043
37044
37045
37046
37047
37048
37049
37050
37051
37052
37053
37054
37055
37056
37057
37058
37059
37060
37061
37062
37063
37064
37065
37066
37067
37068
37069
37070
37071
37072
37073
37074
37075
37076
37077
37078
37079
37080
37081
37082
37083
37084
37085
37086
37087
37088
37089
37090
37091
37092
37093
37094
37095
37096
37097
37098
37099
37100
37101
37102
37103
37104
37105
37106
37107
37108
37109
37110
37111
37112
37113
37114
37115
37116
37117
37118
37119
37120
37121
37122
37123
37124
37125
37126
37127
37128
37129
37130
37131
37132
37133
37134
37135
37136
37137
37138
37139
37140
37141
37142
37143
37144
37145
37146
37147
37148
37149
37150
37151
37152
37153
37154
37155
37156
37157
37158
37159
37160
37161
37162
37163
37164
37165
37166
37167
37168
37169
37170
37171
37172
37173
37174
37175
37176
37177
37178
37179
37180
37181
37182
37183
37184
37185
37186
37187
37188
37189
37190
37191
37192
37193
37194
37195
37196
37197
37198
37199
37200
37201
37202
37203
37204
37205
37206
37207
37208
37209
37210
37211
37212
37213
37214
37215
37216
37217
37218
37219
37220
37221
37222
37223
37224
37225
37226
37227
37228
37229
37230
37231
37232
37233
37234
37235
37236
37237
37238
37239
37240
37241
37242
37243
37244
37245
37246
37247
37248
37249
37250
37251
37252
37253
37254
37255
37256
37257
37258
37259
37260
37261
37262
37263
37264
37265
37266
37267
37268
37269
37270
37271
37272
37273
37274
37275
37276
37277
37278
37279
37280
37281
37282
37283
37284
37285
37286
37287
37288
37289
37290
37291
37292
37293
37294
37295
37296
37297
37298
37299
37300
37301
37302
37303
37304
37305
37306
37307
37308
37309
37310
37311
37312
37313
37314
37315
37316
37317
37318
37319
37320
37321
37322
37323
37324
37325
37326
37327
37328
37329
37330
37331
37332
37333
37334
37335
37336
37337
37338
37339
37340
37341
37342
37343
37344
37345
37346
37347
37348
37349
37350
37351
37352
37353
37354
37355
37356
37357
37358
37359
37360
37361
37362
37363
37364
37365
37366
37367
37368
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result {12:34:56-0500}

test clock-44.2 {regression test - time zone containing only two digits} \
    -body {
	clock scan 1985-04-12T10:15:30+04 -format %Y-%m-%dT%H:%M:%S%Z
    } \
    -result 482134530

test clock-44.3 {regression test - spaces between some scan tokens are optional (TCL_CLOCK_FULL_COMPAT, no-strict only)} \
    -body {
	list [clock scan {9 Apr 2024} -format {%d %b%Y} -gmt 1] \
	     [clock scan {Tue, 9 Apr 2024 00:00:00 +0000} -format {%a, %d %b%Y %H:%M:%S %Z} -gmt 1]
    } \
    -result {1712620800 1712620800}
test clock-44.4 {regression test - spaces between all scan tokens are optional (TCL_CLOCK_FULL_COMPAT, no-strict only)} \
    -body {
	list [clock scan {9 Apr 2024} -format {%d%b%Y} -gmt 1] \
	     [clock scan {Tue, 9 Apr 2024 00:00:00 +0000} -format {%a,%d%b%Y%H:%M:%S%Z} -gmt 1]
    } \
    -result {1712620800 1712620800}

test clock-45.1 {compat: scan regression on spaces (multiple spaces in format)} \
    -body {
	list \
	    [clock scan "11/08/2018  0612"      -format "%m/%d/%Y  %H%M" -gmt 1] \
	    [clock scan "11/08/2018   0612"     -format "%m/%d/%Y   %H%M" -gmt 1] \
	    [clock scan "11/08/2018    0612"    -format "%m/%d/%Y   %H%M" -gmt 1] \
	    [clock scan "  11/08/2018  0612"    -format "  %m/%d/%Y  %H%M" -gmt 1] \
	    [clock scan "  11/08/2018   0612"   -format "  %m/%d/%Y   %H%M" -gmt 1] \
	    [clock scan "  11/08/2018    0612"  -format "  %m/%d/%Y   %H%M" -gmt 1] \
	    [clock scan "11/08/2018  0612  "    -format "%m/%d/%Y  %H%M  " -gmt 1] \
	    [clock scan "11/08/2018   0612  "   -format "%m/%d/%Y   %H%M  " -gmt 1] \
	    [clock scan "11/08/2018    0612  "  -format "%m/%d/%Y   %H%M  " -gmt 1]
    } -result [lrepeat 9 1541657520]

test clock-45.2 {compat: scan regression on spaces (multiple leading/trailing spaces in input)} \
    -body {
	set sp [string repeat " " 20]
	list \
	    [clock scan "NOV   7${sp}"             -format "%b %d" -base 0 -gmt 1 -locale en] \
	    [clock scan "${sp}NOV   7"             -format "%b %d" -base 0 -gmt 1 -locale en] \
	    [clock scan "${sp}NOV   7${sp}"        -format "%b %d" -base 0 -gmt 1 -locale en] \
	    [clock scan "1970   NOV   7${sp}"      -format "%Y %b %d" -gmt 1 -locale en] \
	    [clock scan "${sp}1970   NOV   7"      -format "%Y %b %d" -gmt 1 -locale en] \
	    [clock scan "${sp}1970   NOV   7${sp}" -format "%Y %b %d" -gmt 1 -locale en]
    } -result [lrepeat 6 26784000]
test clock-45.3 {compat: scan regression on spaces (shortest match)} \
    -body {
	list \
	    [clock scan "11 1 120" -format "%y%m%d %H%M%S" -gmt 1] \
	    [clock scan "11 1 120 " -format "%y%m%d %H%M%S" -gmt 1] \
	    [clock scan " 11 1 120" -format "%y%m%d %H%M%S" -gmt 1] \
	    [clock scan "11 1 120        " -format "%y%m%d %H%M%S " -gmt 1] \
	    [clock scan "         11 1 120" -format " %y%m%d %H%M%S" -gmt 1]
    } -result [lrepeat 5 978310920]
test clock-45.4 {compat: scan regression on spaces (mandatory leading/trailing spaces in format)} \
    -body {
	list \
	    [catch {clock scan "11 1 120" -format "%y%m%d %H%M%S " -gmt 1} ret] $ret \
	    [catch {clock scan "11 1 120" -format " %y%m%d %H%M%S" -gmt 1} ret] $ret \
	    [catch {clock scan "11 1 120" -format " %y%m%d %H%M%S " -gmt 1} ret] $ret
    } -result [lrepeat 3 1 "input string does not match supplied format"]
test clock-45.5 {regression test - freescan no int overflow} {
    # note that the relative date changes currently reset the time to 00:00,
    # this can be changed later (simply achievable by adding 00:00 if expected):
    list \
	[clock scan "+24856 days" -base 1600000000 -gmt 1] \
	[clock scan "+815 months" -base 1600000000 -gmt 1] \
	[clock scan "+69 years" -base 1600000000 -gmt 1] \
	[clock scan "+596524 hours" -base 1600000000 -gmt 1] \
	[clock scan "+35791395 minutes" -base 1600000000 -gmt 1] \
	[clock scan "+2147483647 seconds" -base 1600000000 -gmt 1]
} {3747513600 3743193600 3777408000 3747486400 3747483700 3747483647}
test clock-45.6 {regression test - freescan no int overflow} {
    # note that the relative date changes currently reset the time to 00:00,
    # this can be changed later (simply achievable by adding 00:00 if expected):
    list \
	[clock scan "-24856 days" -base 2177452800 -gmt 1] \
	[clock scan "-815 months" -base 2177452800 -gmt 1] \
	[clock scan "-69 years" -base 2177452800 -gmt 1] \
	[clock scan "-596524 hours" -base 2177452800 -gmt 1] \
	[clock scan "-35791395 minutes" -base 2177452800 -gmt 1] \
	[clock scan "-2147483647 seconds" -base 2177452800 -gmt 1]
} {29894400 34214400 0 29966400 29969100 29969153}

test clock-46.1 {regression test - month zero} -constraints valid_off \
    -body {
	clock scan 2004-00-00 -format %Y-%m-%d
    } -result [clock scan 2003-11-30 -format %Y-%m-%d]
test clock-46.2 {regression test - month zero} -constraints valid_off \
    -body {
	clock scan 20040000
    } -result [clock scan 2003-11-30 -format %Y-%m-%d]
test clock-46.3 {regression test - month thirteen} -constraints valid_off \
    -body {
	clock scan 2004-13-01 -format %Y-%m-%d
    } -result [clock scan 2005-01-01 -format %Y-%m-%d]
test clock-46.4 {regression test - month thirteen} -constraints valid_off \
    -body {
	clock scan 20041301
    } -result [clock scan 2005-01-01 -format %Y-%m-%d]

test clock-46.5 {regression test - good time} \
    -body {
	# 12:01 apm are valid input strings...
	list [clock scan "12:01 am" -base 0 -gmt 1] \
	     [clock scan "12:01 pm" -base 0 -gmt 1]
    } -result {60 43260}
test clock-46.6 {freescan: regression test - bad time} -constraints valid_off \
    -body {
	# 13:00 am/pm are invalid input strings...
	list [clock scan "13:00 am" -base 0 -gmt 1] \
	     [clock scan "13:00 pm" -base 0 -gmt 1]
    } -result {-1 -1}

proc _invalid_test {args} {
    global valid_mode
    # ensure validation works TZ independently, since the conversion
    # of local time to UTC may adjust date/time tokens, depending on TZ:
    set res {}
    foreach tz {:GMT :CET {} :Europe/Berlin :localtime} {
	foreach {v} $args {
	    if {$valid_mode} { # globally -valid 1
		lappend res [catch {clock scan $v -timezone $tz} msg] $msg
	    } else {
		lappend res [catch {clock scan $v -valid 1 -timezone $tz} msg] $msg
	    }
	}
    }
    set res
}
# test without and with relative offsets:
foreach {idx relstr} {"" "" "+rel" "+ 15 month + 40 days + 30 hours + 80 minutes +9999 seconds"} {
test clock-46.10$idx {freescan: validation rules: invalid time} \
    -body {
	# 13:00 am/pm are invalid input strings...
	_invalid_test "13:00 am$relstr" "13:00 pm$relstr"
    } -result [lrepeat 10 1 {unable to convert input string: invalid time (hour)}]
test clock-46.11$idx {freescan: validation rules: invalid time} \
    -body {
	# invalid minutes in input strings...
	_invalid_test "23:70$relstr" "11:80 pm$relstr"
    } -result [lrepeat 10 1 {unable to convert input string: invalid time (minutes)}]
test clock-46.12$idx {freescan: validation rules: invalid time} \
    -body {
	# invalid seconds in input strings...
	_invalid_test "23:00:70$relstr" "11:00:80 pm$relstr"
    } -result [lrepeat 10 1 {unable to convert input string: invalid time}]
test clock-46.13$idx {freescan: validation rules: invalid day} \
    -body {
	_invalid_test "29 Feb 2017$relstr" "30 Feb 2016$relstr"
    } -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.14$idx {freescan: validation rules: invalid day} \
    -body {
	_invalid_test "0 Feb 2017$relstr" "00 Feb 2017$relstr"
    } -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.15$idx {freescan: validation rules: invalid month} \
    -body {
	_invalid_test "13/13/2017$relstr" "00/00/2017$relstr"
    } -result [lrepeat 10 1 {unable to convert input string: invalid month}]
test clock-46.16$idx {freescan: validation rules: invalid day of week} \
    -body {
	_invalid_test "Sat Jan 02 00:00:00 1970$relstr" "Thu Jan 04 00:00:00 1970$relstr"
    } -result [lrepeat 10 1 {unable to convert input string: invalid day of week}]
test clock-46.17$idx {scan: validation rules: invalid year} -setup {
	set orgcfg [list -min-year [::tcl::unsupported::clock::configure -min-year] -max-year [::tcl::unsupported::clock::configure -max-year] \
	     -year-century [::tcl::unsupported::clock::configure -year-century] -century-switch [::tcl::unsupported::clock::configure -century-switch]]
	::tcl::unsupported::clock::configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
    } -body {
	_invalid_test "70-01-01$relstr" "1870-01-01$relstr" "9570-01-01$relstr"
    } -result [lrepeat 15 1 {unable to convert input string: invalid year}] -cleanup {
	::tcl::unsupported::clock::configure {*}$orgcfg
	unset -nocomplain orgcfg
    }

}; # foreach
rename _invalid_test {}
unset -nocomplain idx relstr

set dst_hole_check {
    {":Europe/Berlin"
	"2017-03-26 01:59:59" "2017-03-26 02:00:00" "2017-03-26 02:59:59" "2017-03-26 03:00:00"
	"2017-10-29 01:59:59" "2017-10-29 02:00:00"}
    {":Europe/Berlin"
	"2018-03-25 01:59:59" "2018-03-25 02:00:00" "2018-03-25 02:59:59" "2018-03-25 03:00:00"
	"2018-10-28 01:59:59" "2018-10-28 02:00:00"}
    {":America/New_York"
	"2017-03-12 01:59:59" "2017-03-12 02:00:00" "2017-03-12 02:59:59" "2017-03-12 03:00:00"
	"2017-11-05 01:59:59" "2017-11-05 02:00:00"}
    {":America/New_York"
	"2018-03-11 01:59:59" "2018-03-11 02:00:00" "2018-03-11 02:59:59" "2018-03-11 03:00:00"
	"2018-11-04 01:59:59" "2018-11-04 02:00:00"}
}
test clock-46.19-1 {free-scan: validation rules: invalid time (DST-hole, out of range in time-zone)} \
    -body {
	set res {}
	foreach tz $dst_hole_check { set dt [lassign $tz tz]; foreach dt $dt {
	    lappend res [set v [catch {clock scan $dt -timezone $tz -valid 1} msg]]
	    if {$v} { lappend res $msg }
	}}
	set res
    } -cleanup {
	unset -nocomplain res v dt tz
    } -result [lrepeat 4 \
	{*}[list 0 {*}[lrepeat 2 1 {unable to convert input string: invalid time (does not exist in this time-zone)}] 0 0 0]]
test clock-46.19-2 {free-scan: validation rules regression: all scans successful, if -valid 0} \
    -body {
	set res {}
	set res {}
	foreach tz $dst_hole_check { set dt [lassign $tz tz]; foreach dt $dt {
	    lappend res [set v [catch {clock scan $dt -timezone $tz} msg]]
	}}
	set res
    } -cleanup {
	unset -nocomplain res v dt tz
    } -result [lrepeat 4 {*}[if {$valid_mode} {list 0 1 1 0 0 0} else {list 0 0 0 0 0 0}]]
test clock-46.19-3 {scan: validation rules: invalid time (DST-hole, out of range in time-zone)} \
    -body {
	set res {}
	foreach tz $dst_hole_check { set dt [lassign $tz tz]; foreach dt $dt {
	    lappend res [set v [catch {clock scan $dt -timezone $tz -format "%Y-%m-%d %H:%M:%S" -valid 1} msg]]
	    if {$v} { lappend res $msg }
	}}
	set res
    } -cleanup {
	unset -nocomplain res v dt tz
    } -result [lrepeat 4 \
	{*}[list 0 {*}[lrepeat 2 1 {unable to convert input string: invalid time (does not exist in this time-zone)}] 0 0 0]]
test clock-46.19-4 {scan: validation rules regression: all scans successful, if -valid 0} \
    -body {
	set res {}
	set res {}
	foreach tz $dst_hole_check { set dt [lassign $tz tz]; foreach dt $dt {
	    lappend res [set v [catch {clock scan $dt -timezone $tz -format "%Y-%m-%d %H:%M:%S"} msg]]
	}}
	set res
    } -cleanup {
	unset -nocomplain res v dt tz
    } -result [lrepeat 4 {*}[if {$valid_mode} {list 0 1 1 0 0 0} else {list 0 0 0 0 0 0}]]
unset -nocomplain dst_hole_check

proc _invalid_test {args} {
    global valid_mode
    # ensure validation works TZ independently, since the conversion
    # of local time to UTC may adjust date/time tokens, depending on TZ:
    set res {}
    foreach tz {:GMT :CET {} :Europe/Berlin :localtime} {
	foreach {v fmt} $args {
	    if {$valid_mode} { # globally -valid 1
		lappend res [catch {clock scan $v -format $fmt -timezone $tz} msg] $msg
	    } else {
		lappend res [catch {clock scan $v -format $fmt -valid 1 -timezone $tz} msg] $msg
	    }
	}
    }
    set res
}
test clock-46.20 {scan: validation rules: invalid time} \
    -body {
	# 13:00 am/pm are invalid input strings...
	_invalid_test "13:00 am" "%H:%M %p" "13:00 pm" "%H:%M %p"
    } -result [lrepeat 10 1 {unable to convert input string: invalid time (hour)}]
test clock-46.21 {scan: validation rules: invalid time} \
    -body {
	# invalid minutes in input strings...
	_invalid_test "23:70" "%H:%M" "11:80 pm" "%H:%M %p"
    } -result [lrepeat 10 1 {unable to convert input string: invalid time (minutes)}]
test clock-46.22 {scan: validation rules: invalid time} \
    -body {
	# invalid seconds in input strings...
	_invalid_test "23:00:70" "%H:%M:%S" "11:00:80 pm" "%H:%M:%S %p"
    } -result [lrepeat 10 1 {unable to convert input string: invalid time}]
test clock-46.23 {scan: validation rules: invalid day} \
    -body {
	_invalid_test "29 Feb 2017" "%d %b %Y" "30 Feb 2016" "%d %b %Y"
    } -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.24 {scan: validation rules: invalid day} \
    -body {
	_invalid_test "0 Feb 2017" "%d %b %Y" "00 Feb 2017" "%d %b %Y"
    } -result [lrepeat 10 1 {unable to convert input string: invalid day}]
test clock-46.25 {scan: validation rules: invalid month} \
    -body {
	_invalid_test "13/13/2017" "%m/%d/%Y" "00/01/2017" "%m/%d/%Y"
    } -result [lrepeat 10 1 {unable to convert input string: invalid month}]
test clock-46.26 {scan: validation rules: ambiguous day} \
    -body {
	_invalid_test "1970-01-02--004" "%Y-%m-%d--%j" "70-01-02--004" "%y-%m-%d--%j"
    } -result [lrepeat 10 1 {unable to convert input string: ambiguous day}]
test clock-46.27 {scan: validation rules: ambiguous year} \
    -body {
	_invalid_test "19700106 00W014" "%Y%m%d %gW%V%u" "1970006 00W014" "%Y%j %gW%V%u"
    } -result [lrepeat 10 1 {unable to convert input string: ambiguous year}]
test clock-46.28 {scan: validation rules: invalid day of week} \
    -body {
	_invalid_test "Sat Jan 02 00:00:00 1970" "%a %b %d %H:%M:%S %Y"
    } -result [lrepeat 5 1 {unable to convert input string: invalid day of week}]
test clock-46.29-1 {scan: validation rules: invalid day of year} \
    -body {
	_invalid_test "000-2017" "%j-%Y" "366-2017" "%j-%Y" "000-2017" "%j-%G" "366-2017" "%j-%G"
    } -result [lrepeat 20 1 {unable to convert input string: invalid day of year}]
test clock-46.29-2 {scan: validation rules: valid day of leap/not leap year} \
    -body {
	list [clock format [clock scan "366-2016" -format "%j-%Y" -valid 1 -gmt 1] -format "%d-%m-%Y" -gmt 1] \
	     [clock format [clock scan "365-2017" -format "%j-%Y" -valid 1 -gmt 1] -format "%d-%m-%Y" -gmt 1] \
	     [clock format [clock scan "366-2016" -format "%j-%G" -valid 1 -gmt 1] -format "%d-%m-%Y" -gmt 1] \
	     [clock format [clock scan "365-2017" -format "%j-%G" -valid 1 -gmt 1] -format "%d-%m-%Y" -gmt 1]
    } -result {31-12-2016 31-12-2017 31-12-2016 31-12-2017}
test clock-46.30 {scan: validation rules: invalid year} -setup {
	set orgcfg [list -min-year [::tcl::unsupported::clock::configure -min-year] -max-year [::tcl::unsupported::clock::configure -max-year] \
	     -year-century [::tcl::unsupported::clock::configure -year-century] -century-switch [::tcl::unsupported::clock::configure -century-switch]]
	::tcl::unsupported::clock::configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
    } -body {
	_invalid_test "01-01-70" "%d-%m-%y" "01-01-1870" "%d-%m-%C%y" "01-01-1970" "%d-%m-%Y"
    } -result [lrepeat 15 1 {unable to convert input string: invalid year}] -cleanup {
	::tcl::unsupported::clock::configure {*}$orgcfg
	unset -nocomplain orgcfg
    }
test clock-46.31 {scan: validation rules: invalid iso year} -setup {
	set orgcfg [list -min-year [::tcl::unsupported::clock::configure -min-year] -max-year [::tcl::unsupported::clock::configure -max-year] \
	     -year-century [::tcl::unsupported::clock::configure -year-century] -century-switch [::tcl::unsupported::clock::configure -century-switch]]
	::tcl::unsupported::clock::configure -min-year 2000 -max-year 2100 -year-century 2000 -century-switch 38
    } -body {
	_invalid_test "01-01-70" "%d-%m-%g" "01-01-9870" "%d-%m-%C%g" "01-01-9870" "%d-%m-%G"
    } -result [lrepeat 15 1 {unable to convert input string: invalid iso year}] -cleanup {
	::tcl::unsupported::clock::configure {*}$orgcfg
	unset -nocomplain orgcfg
    }
rename _invalid_test {}

test clock-47.1 {regression test - four-digit time} {
    clock scan 0012
} [clock scan 0012 -format %H%M]
test clock-47.2 {regression test - four digit time} {
    clock scan 0039
} [clock scan 0039 -format %H%M]
36763
36764
36765
36766
36767
36768
36769








36770
36771
36772
36773
36774
36775
36776
    }
    -result {Sun Jan 08 22:30:06 WAST 2012}
}

test clock-57.1 {clock scan - abbreviated options} {
    clock scan 1970-01-01 -f %Y-%m-%d -g true
} 0









test clock-58.1 {clock l10n - Japanese localisation} {*}{
    -setup {
	proc backslashify { string } {

	    set retval {}
	    foreach char [split $string {}] {







>
>
>
>
>
>
>
>







38035
38036
38037
38038
38039
38040
38041
38042
38043
38044
38045
38046
38047
38048
38049
38050
38051
38052
38053
38054
38055
38056
    }
    -result {Sun Jan 08 22:30:06 WAST 2012}
}

test clock-57.1 {clock scan - abbreviated options} {
    clock scan 1970-01-01 -f %Y-%m-%d -g true
} 0

test clock-57.2 {clock scan - not -gmt and -timezone in the same call} {
    catch {clock scan 1970-01-01 -format %Y-%m-%d -gmt true -timezone :Europe/Berlin}
} 1

test clock-57.3 {clock scan - not -g and -timezone in the same call} {
    catch {clock scan 1970-01-01 -format %Y-%m-%d -g true -timezone :Europe/Berlin}
} 1

test clock-58.1 {clock l10n - Japanese localisation} {*}{
    -setup {
	proc backslashify { string } {

	    set retval {}
	    foreach char [split $string {}] {
36785
36786
36787
36788
36789
36790
36791
36792
36793
36794
36795
36796
36797
36798
36799
36800
36801
36802
36803
36804
36805
36806
36807
36808
	    }
	    return $retval
	}
    }
    -body {
	set trouble {}
	foreach {date jdate} {
	    1872-12-31 \u897f\u66a61872\u5e7412\u670831\u65e5
	    1873-01-01 \u660e\u6cbb06\u5e7401\u670801\u65e5
	    1912-07-29 \u660e\u6cbb45\u5e7407\u670829\u65e5
	    1912-07-30 \u5927\u6b6301\u5e7407\u670830\u65e5
	    1926-12-24 \u5927\u6b6315\u5e7412\u670824\u65e5
	    1926-12-25 \u662d\u548c01\u5e7412\u670825\u65e5
	    1989-01-07 \u662d\u548c64\u5e7401\u670807\u65e5
	    1989-01-08 \u5e73\u621001\u5e7401\u670808\u65e5
	    2019-04-30 \u5e73\u621031\u5e7404\u670830\u65e5
	    2019-05-01 \u4ee4\u548c01\u5e7405\u670801\u65e5
	} {
	    set status [catch {
		set secs [clock scan $date \
			      -timezone +0900 \
			      -locale ja_JP \
			      -format %Y-%m-%d]
		set jda [clock format $secs \







|
|
|
|
|
|
|
|
|
|







38065
38066
38067
38068
38069
38070
38071
38072
38073
38074
38075
38076
38077
38078
38079
38080
38081
38082
38083
38084
38085
38086
38087
38088
	    }
	    return $retval
	}
    }
    -body {
	set trouble {}
	foreach {date jdate} {
	    1872-12-31 西暦18721231
	    1873-01-01 明治060101
	    1912-07-29 明治450729
	    1912-07-30 大正01年0730
	    1926-12-24 大正151224
	    1926-12-25 昭和011225
	    1989-01-07 昭和640107
	    1989-01-08 平成010108
	    2019-04-30 平成310430
	    2019-05-01 令和010501
	} {
	    set status [catch {
		set secs [clock scan $date \
			      -timezone +0900 \
			      -locale ja_JP \
			      -format %Y-%m-%d]
		set jda [clock format $secs \
36915
36916
36917
36918
36919
36920
36921









36922
36923
36924
36925
36926
36927
36928

36929
36930








36931
36932
36933
36934
36935

36936






36937
36938
36939
36940
36941
36942
36943
} [clock scan "2000-12-01" -gmt true -format "%Y-%m-%d"]

test clock-61.1 {overflow of a wide integer on output} {*}{
    -body {
	clock format 0x8000000000000000 -format %s -gmt true
    }
    -result {integer value too large to represent}









    -returnCodes error
}
test clock-61.2 {overflow of a wide integer on output} {*}{
    -body {
	clock format -0x8000000000000001 -format %s -gmt true
    }
    -result {integer value too large to represent}

    -returnCodes error
}








test clock-61.3 {near-miss overflow of a wide integer on output} {
    clock format 0x7fffffffffffffff -format %s -gmt true
} [expr 0x7fffffffffffffff]
test clock-61.4 {near-miss overflow of a wide integer on output} {
    clock format -0x8000000000000000 -format %s -gmt true

} [expr -0x8000000000000000]







test clock-62.1 {Bug 1902423} {*}{
    -setup {::tcl::clock::ClearCaches}
    -body {
	set s 1204049747
	set f1 [clock format $s -format {%Y-%m-%d %T} -locale C]
	set f2 [clock format $s -format {%Y-%m-%d %H:%M:%S} -locale C]







>
>
>
>
>
>
>
>
>







>


>
>
>
>
>
>
>
>
|
|
|
|
|
>
|
>
>
>
>
>
>







38195
38196
38197
38198
38199
38200
38201
38202
38203
38204
38205
38206
38207
38208
38209
38210
38211
38212
38213
38214
38215
38216
38217
38218
38219
38220
38221
38222
38223
38224
38225
38226
38227
38228
38229
38230
38231
38232
38233
38234
38235
38236
38237
38238
38239
38240
38241
38242
38243
38244
38245
38246
38247
38248
} [clock scan "2000-12-01" -gmt true -format "%Y-%m-%d"]

test clock-61.1 {overflow of a wide integer on output} {*}{
    -body {
	clock format 0x8000000000000000 -format %s -gmt true
    }
    -result {integer value too large to represent}
    -errorCode {CLOCK badOption 0x8000000000000000}
    -returnCodes error
}
test clock-61.1b {overflow of a wide integer on base} {*}{
    -body {
	clock scan "" -base 0x8000000000000000 -gmt true
    }
    -result {integer value too large to represent}
    -errorCode {CLOCK badOption 0x8000000000000000}
    -returnCodes error
}
test clock-61.2 {overflow of a wide integer on output} {*}{
    -body {
	clock format -0x8000000000000001 -format %s -gmt true
    }
    -result {integer value too large to represent}
    -errorCode {CLOCK badOption -0x8000000000000001}
    -returnCodes error
}
test clock-61.2b {overflow of a wide integer on base} {*}{
    -body {
	clock scan "" -base -0x8000000000000001 -gmt true
    }
    -result {integer value too large to represent}
    -errorCode {CLOCK badOption -0x8000000000000001}
    -returnCodes error
}
test clock-61.3 {near-miss overflow of a wide integer on output, very large datetime (upper range)} {
    clock format 0x00F0000000000000 -format "%s %Y %EE" -gmt true
} [list [expr 0x00F0000000000000] 2140702833 C.E.]
test clock-61.4 {near-miss overflow of a wide integer on output, very small datetime (lower range)} {
    clock format -0x00F0000000000000 -format "%s %Y %EE" -gmt true
} [list [expr -0x00F0000000000000] 2140654939 B.C.E.]

test clock-61.5 {overflow of possible date-time (upper range)} -body {
    clock format 0x00F0000000000001 -gmt true
} -returnCodes error -result {integer value too large to represent} -errorCode {CLOCK badOption 0x00F0000000000001}
test clock-61.6 {overflow of possible date-time (lower range)} -body {
    clock format -0x00F0000000000001 -gmt true
} -returnCodes error -result {integer value too large to represent} -errorCode {CLOCK badOption -0x00F0000000000001}

test clock-62.1 {Bug 1902423} {*}{
    -setup {::tcl::clock::ClearCaches}
    -body {
	set s 1204049747
	set f1 [clock format $s -format {%Y-%m-%d %T} -locale C]
	set f2 [clock format $s -format {%Y-%m-%d %H:%M:%S} -locale C]
36975
36976
36977
36978
36979
36980
36981









36982
36983
36984
36985
36986
36987
36988
    -body {
	clock add 0 1 year -foo bar
    }
    -match glob
    -returnCodes error
    -result {bad option "-foo"*}
}










test clock-66.1 {clock scan, no date, never-before-seen timezone} {*}{
    -setup {
	::tcl::clock::ClearCaches
    }
    -body {
	clock scan 1200 \







>
>
>
>
>
>
>
>
>







38280
38281
38282
38283
38284
38285
38286
38287
38288
38289
38290
38291
38292
38293
38294
38295
38296
38297
38298
38299
38300
38301
38302
    -body {
	clock add 0 1 year -foo bar
    }
    -match glob
    -returnCodes error
    -result {bad option "-foo"*}
}

test clock-65.2 {clock add with both -timezone and -gmt} {*}{
    -body {
	clock add 0 1 year -timezone :CET -gmt true
    }
    -match glob
    -returnCodes error
    -result {cannot use -gmt and -timezone in same call}
}

test clock-66.1 {clock scan, no date, never-before-seen timezone} {*}{
    -setup {
	::tcl::clock::ClearCaches
    }
    -body {
	clock scan 1200 \
37027
37028
37029
37030
37031
37032
37033
37034
37035








37036



37037
37038
37039
37040
37041
    expr {$res == [clock scan "01/01/1970" -locale current -format %x -gmt 1]}
} -cleanup {
    msgcat::mclocale $current
} -result {1}

# cleanup

namespace delete ::testClock
::tcl::clock::ClearCaches








::tcltest::cleanupTests



return

# Local Variables:
# mode: tcl
# End:







<

>
>
>
>
>
>
>
>

>
>
>





38341
38342
38343
38344
38345
38346
38347

38348
38349
38350
38351
38352
38353
38354
38355
38356
38357
38358
38359
38360
38361
38362
38363
38364
38365
    expr {$res == [clock scan "01/01/1970" -locale current -format %x -gmt 1]}
} -cleanup {
    msgcat::mclocale $current
} -result {1}

# cleanup


::tcl::clock::ClearCaches
rename test {}
namespace import -force ::tcltest::*
# adjust expected skipped (valid_off is an artificial constraint):
if {$valid_mode && [info exists ::tcltest::skippedBecause(valid_off)]} {
    incr ::tcltest::numTests(Total) -$::tcltest::skippedBecause(valid_off)
    incr ::tcltest::numTests(Skipped) -$::tcltest::skippedBecause(valid_off)
    unset ::tcltest::skippedBecause(valid_off)
}
::tcltest::cleanupTests
namespace delete ::testClock
unset valid_mode

return

# Local Variables:
# mode: tcl
# End:

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
# 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.
#
# 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]]

testConstraint testchmod       [llength [info commands testchmod]]
testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testvolumetype  [llength [info commands testvolumetype]]

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)]}]



global env
set cmdAHwd [pwd]
catch {set platform [testgetplatform]}

proc waitForEvenSecondForFAT {} {
    # Windows 9x uses filesystems (the FAT* family of FSes) without enough






|
|










|




>





|
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 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 © 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 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 linkDirectory [expr {
    ![testConstraint win] ||
    ($::tcl_platform(osVersion) >= 5.0
     && [lindex [file system [temporaryDirectory]] 1] eq "NTFS")
}]
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
    set oldpwd [pwd]
    set temp $env(HOME)
    file delete -force $foodir
} -body {
    set env(HOME) $oldpwd
    file mkdir $foodir
    cd $foodir
    cd ~
    string equal [pwd] $oldpwd
} -cleanup {
    cd $oldpwd
    file delete $foodir
    set env(HOME) $temp
} -result 1
test cmdAH-2.4 {Tcl_CdObjCmd} -setup {







|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    set oldpwd [pwd]
    set temp $env(HOME)
    file delete -force $foodir
} -body {
    set env(HOME) $oldpwd
    file mkdir $foodir
    cd $foodir
    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
    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}
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
} -cleanup {
    cd $dir
} -match glob -result "couldn't change working directory to \".\0\": *"
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 {}}























































































































test cmdAH-4.1 {Tcl_EncodingObjCmd} -returnCodes error -body {
    encoding
} -result {wrong # args: should be "encoding subcommand ?arg ...?"}
test cmdAH-4.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 {
    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 convertto \u4e4e
} -cleanup {
    encoding system $system
} -result 8C
test cmdAH-4.6 {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


































































































































































































































































































































































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}
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








|
>
>
>
>
>
>
>
>
>
>
>
>
>
|

















|


|

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


|

|
|
<
<
<
<
<
<
<
<
>
|
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
    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 {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 .\x00
} -cleanup {
    cd $dir
} -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.1 {encoding} -returnCodes error -body {
    encoding
} -result {wrong # args: should be "encoding subcommand ?arg ...?"}
test cmdAH-4.1.2 {Tcl_EncodingObjCmd} -returnCodes error -body {
    encoding foo
} -result {unknown or ambiguous subcommand "foo": must be convertfrom, convertto, dirs, names, profiles, or system}









#
# encoding system 4.2.*


badnumargs cmdAH-4.2.1 {encoding system} {ascii ascii}

test cmdAH-4.2.2 {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, 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
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
} /
test cmdAH-8.15 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname //foo/bar
} /foo
test cmdAH-8.16 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname {//foo\/bar/baz}
} {/foo\/bar}
test cmdAH-8.17 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname {//foo\/bar/baz/blat}
} {/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







|



|



|



|







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
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
test cmdAH-8.16 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname {//foo\/bar/baz}
} {//foo\/bar}
test cmdAH-8.17 {Tcl_FileObjCmd: dirname} testsetplatform {
    testsetplatform unix
    file dirname {//foo\/bar/baz/blat}
} {//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
} ~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 ~
} -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 ~
} -cleanup {
    set env(HOME) $temp
} -result ~
test cmdAH-8.45 {Tcl_FileObjCmd: dirname} -setup {
    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}
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"







|









|


|
|
<
<
<
<

<
<
|







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
} ~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 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 home]
} -cleanup {
    set env(HOME) $temp
} -result .
test cmdAH-8.45 {Tcl_FileObjCmd: dirname ~} -body {




    file dirname ~


} -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
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}







|







893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
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
} {}
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
    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 {
    global env
    set temp $env(HOME)
} -body {
    set env(HOME) "/home/test"
    testsetplatform unix
    file tail ~
} -cleanup {
    set env(HOME) $temp
} -result test
test cmdAH-9.43 {Tcl_FileObjCmd: tail} -constraints testsetplatform -setup {
    global env
    set temp $env(HOME)
} -body {
    set env(HOME) "~"
    testsetplatform unix
    file tail ~
} -cleanup {
    set env(HOME) $temp
} -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







|
<
<
<
<
<

<
<
|






|


|
<
<
<
<
<
<
<
<
<
<







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
    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 ~} -body {





    file tail ~


} -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 home]
} -cleanup {
    set env(HOME) $temp
} -result ~










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
} 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]

# 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







|







985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
} 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]

# 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
    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}

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
}
test cmdAH-16.3 {Tcl_FileObjCmd: readable} {
    -constraints {unix notRoot testchmod}
    -setup  	 {testchmod 0o333 $gorpfile}
    -body   	 {file readable $gorpfile}
    -result 	 0
}

# writable
test cmdAH-17.1 {Tcl_FileObjCmd: writable} {







|


















|







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
    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 {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
}
test cmdAH-16.3 {Tcl_FileObjCmd: readable} {
    -constraints {unix notRoot testchmod notWsl}
    -setup  	 {testchmod 0o333 $gorpfile}
    -body   	 {file readable $gorpfile}
    -result 	 0
}

# writable
test cmdAH-17.1 {Tcl_FileObjCmd: writable} {
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
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} {
    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







|







1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
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 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
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
} -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 *
# 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 exists /tmp/tcl.foo.dir/file
} -cleanup {
    file attributes /tmp/tcl.foo.dir -permissions 0775
    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







<

|









|


|







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
} -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 {

    file nativename ~nOsUcHuSeR
} -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 0
    file exists /tmp/tcl.foo.dir/file
} -cleanup {
    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
} -result {1 0}

# Stat related commands

catch {testsetplatform $platform}
removeFile $gorpfile
set gorpfile [makeFile "Test string" gorp.file]
catch {file attributes $gorpfile -permissions 0765}

# 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]
}







|







1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
} -result {1 0}

# Stat related commands

catch {testsetplatform $platform}
removeFile $gorpfile
set gorpfile [makeFile "Test string" gorp.file]
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
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"}
test cmdAH-23.2 {Tcl_FileObjCmd: lstat} -returnCodes error -body {
    file lstat a b c
} -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)
} -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







|


|










|







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
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 {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?"}
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) & 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
    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
    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"}







|







1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
    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 
    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
    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
    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"}







|







1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
    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 
    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
} -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 {
    set filename [makeFile "" foo.text]
} -body {


    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 {
    set filename [makeFile "" foo.text]
} -body {


    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 {







|



>
>







>
>







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
} -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 {
    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 {
    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 {
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
    }
    set res
} -result 0

catch {testsetplatform $platform}
removeFile $gorpfile
set gorpfile [makeFile "Test string" gorp.file]
catch {file attributes $gorpfile -permissions 0765}

# stat
test cmdAH-28.1 {Tcl_FileObjCmd: stat} -returnCodes error -body {
    file stat _bogus_
} -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"}
test cmdAH-28.3 {Tcl_FileObjCmd: stat} -setup {
    unset -nocomplain stat
    set stat(blocks) [set stat(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 {
    unset -nocomplain stat
} -body {
    file stat $gorpfile stat
    expr {$stat(mode) & 0o777}
} -result {501}
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







|



|
|


|


|











|



|
|







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
    }
    set res
} -result 0

catch {testsetplatform $platform}
removeFile $gorpfile
set gorpfile [makeFile "Test string" gorp.file]
catch {file attributes $gorpfile -permissions 0o765}

# stat
test cmdAH-28.1 {Tcl_FileObjCmd: stat} -returnCodes error -body {
    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?"}
test cmdAH-28.3 {Tcl_FileObjCmd: stat} -setup {
    unset -nocomplain stat
    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 notWsl} -setup {
    unset -nocomplain stat
} -body {
    file stat $gorpfile stat
    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
	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}










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} {







>
>
>
>
>
>
>
>
>
>







1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
	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
    }
    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}
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







|


















<
<
<







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
    }
    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, 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 *}




# 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
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()
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}







|







2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
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()
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

# cleanup
catch {testsetplatform $platform}
unset -nocomplain platform

# Tcl_ForObjCmd is tested in for.test

catch {file attributes $dirfile -permissions 0777}
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:







|













2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210

# cleanup
catch {testsetplatform $platform}
unset -nocomplain platform

# Tcl_ForObjCmd is tested in for.test

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
# 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.
#
# 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]]

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]












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"}




|
|











|



>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 © 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 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
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]
test cmdIL-1.38 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} {
    lsort -ascii -nocase [list \0 \x7f \x80 \uffff]
} [list \0 \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]
test cmdIL-1.40 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} {
    lsort -ascii -nocase [list \0 \x7f \x80 \U01ffff \uffff]
} [list \0 \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}




# 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)}]
    }
} -body {
    for {set i 0} {$i < 150} {incr i} {
	set x {}
	for {set j 0} {$j < $i} {incr j} {
	    lappend x [expr {[rand] & 0xfff}]
	}







|
|

|
|

|
|

|
|






>
>
>









|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
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 \x00 \x7F \x80 \uFFFF]
} [list \x00 \x7F \x80 \uFFFF]
test cmdIL-1.38 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} {
    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 \x00 \x7F \x80 \U01ffff \uFFFF]
} [list \x00 \x7F \x80 \uFFFF \U01ffff]
test cmdIL-1.40 {Tcl_LsortObjCmd procedure, Bug 8e1e31eac0fd6b6c} {
    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)}]
    }
} -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
    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"]
    ::tcltest::restore_locale
    set result
} "A a B b C c \xe3 \xc4"
test cmdIL-4.25 {DictionaryCompare procedure, international characters} {hasIsoLocale} {
    ::tcltest::set_iso8859_1_locale
    set result [lsort -dictionary "a23\xe3 a23\xc5 a23\xe4"]
    ::tcltest::restore_locale
    set result
} "a23\xe3 a23\xe4 a23\xc5"
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} {







|


|


|


|







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 ã Ä"]
    ::tcltest::restore_locale
    set result
} "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ã a23Å a23ä"]
    ::tcltest::restore_locale
    set result
} "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
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
} {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
} {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}







|


|







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\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\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
} {{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)
    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}}







|







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)}
    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}}
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
    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 {
    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 {
    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-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\""







|





|






>
>
>
>
>
>
>
>
>
>
>
>







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 (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 (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
} {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 {
    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}







|







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 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}

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
# 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.
#
# 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]]

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








|
|
|










|







1
2
3
4
5
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 © 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 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

Changes to tests/cmdMZ.test.

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.
#
# 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::*






|
|
|







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 © 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
} -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
    # caching causes this to fail. The caching is strictly incorrect, but we
    # have no control over that.
    file attr . -permissions 000
    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







|
|


|







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
    # caching causes this to fail. The caching is strictly incorrect, but we
    # have no control over that.
    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
    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 {}
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} {







|







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}
} -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} {
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
            append x $f
        }
        return $x
    }}
} {]\n}
test cmdMZ-4.11 {Tcl_SplitObjCmd: basic split commands} {
    apply {{} {
        set x ab\000c
        set y [split $x {}]
	binary scan $y c* z
        return $z
    }}
} {97 32 98 32 0 32 99}
test cmdMZ-4.12 {Tcl_SplitObjCmd: basic split commands} {
    split "a0ab1b2bbb3\000c4" ab\000c
} {{} 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"

# 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):







|






|


|
|
|







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
            append x $f
        }
        return $x
    }}
} {]\n}
test cmdMZ-4.11 {Tcl_SplitObjCmd: basic split commands} {
    apply {{} {
        set x ab\x00c
        set y [split $x {}]
	binary scan $y c* z
        return $z
    }}
} {97 32 98 32 0 32 99}
test cmdMZ-4.12 {Tcl_SplitObjCmd: basic split commands} {
    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å {} N wq"
    split "ab qw幎N wq" " "
} "a b qwN 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):
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
} {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 {
    set m1 [timerate {_nrt_sleep 0.01} 50]
    set m2 [timerate {_nrt_sleep 1.00} 50]
    list [list \
	[expr {[lindex $m1 0] < [lindex $m2 0]}] \
	[expr {[lindex $m1 0] < 100}] \
	[expr {[lindex $m2 0] > 100}] \
	[expr {[lindex $m1 2] > 500}] \







|







397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
} {1 {missing close-brace}}
test cmdMZ-6.5a {Tcl_TimeRateObjCmd: result format and one iteration} {
    regexp {^\d+(?:\.\d+)? \ws/# 1 # \d+(?:\.\d+)? #/sec \d+(?:\.\d+)? net-ms$} [timerate {} 0]
} 1
test cmdMZ-6.5b {Tcl_TimeRateObjCmd: result format without iterations} {
    regexp {^0 \ws/# 0 # 0 #/sec 0 net-ms$} [timerate {} 0 0]
} 1
test cmdMZ-6.6 {Tcl_TimeRateObjCmd: slower commands take longer, but it remains almost the same time of measurement} -body {
    set m1 [timerate {_nrt_sleep 0.01} 50]
    set m2 [timerate {_nrt_sleep 1.00} 50]
    list [list \
	[expr {[lindex $m1 0] < [lindex $m2 0]}] \
	[expr {[lindex $m1 0] < 100}] \
	[expr {[lindex $m2 0] > 100}] \
	[expr {[lindex $m1 2] > 500}] \

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
# 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.
#
# 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    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
}








|
|




















|

|









|

|

|





|

|









|

|

|











<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80



81
82
83
84
85
86
87
# 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 © 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    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]




# procedures used below

proc put_hello_char {c} {
    global a
    append a [format %c $c]
    return $c
}

Changes to tests/compExpr.test.

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.
#
# 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::*




|
|







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 © 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
    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)]
} 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)))]
} 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*}







|








|







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)}]
} 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)))}]
} 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*}
366
367
368
369
370
371
372
373



































374
375
376

377
378
379
380
381
382
383
        set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    unset end i tmp
    rename getbytes {}
} -result 0




































# cleanup
catch {unset a}
catch {unset b}

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>







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
        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
# 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.
#
# 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]]

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.







|
|











|







1
2
3
4
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 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 © 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 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.
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] {} {
	set j [incr i]
	if {$j > 3} break
    }
    set j
} {4}

test compile-5.1 {TclCompileForeachCmd: exception stack} {







|







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}] {} {
	set j [incr i]
	if {$j > 3} break
    }
    set j
} {4}

test compile-5.1 {TclCompileForeachCmd: exception stack} {
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
    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] {
	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
} {0 4}
test compile-8.2 {CollectArgInfo: binary data} {
    list [catch "string length foo\000" 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 {} {







|







|


|







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
    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}] {
	set j [incr i]
	if {$j > 3} break
    }
    set j
} {4}

test compile-8.1 {CollectArgInfo: binary data} {
    list [catch "string length \x00foo" msg] $msg
} {0 4}
test compile-8.2 {CollectArgInfo: binary data} {
    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 {} {
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 }}
} -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







|







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 [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
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
    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)
    ti eval {foreach cmd {eval "if 1" try catch} {
	set c [gencode [expr {![::tcl::pkgconfig get 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:
    ti eval {set result}
} -result {}
#
# clean up:
if {[interp exists ti]} {
    interp delete ti
}







|



















|







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
    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)
    ti eval {foreach cmd {eval "if 1" try catch} {
	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
    # 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
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 {
    interp alias {} run {} testevalex
    set constraints testevalex
} else {
    interp alias {} run {} if 1
    set constraints {}
}








|







562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
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} {
    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
# 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}]
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}]
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}]
# 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}]
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]]
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 {}{}}
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}}







|





|





|






|








|











|







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
# 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 {}
}  -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 {}
}  -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 {}
}  -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 {}
}  -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 {}
} -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
} -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}}

Changes to tests/concat.test.

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.
#
# 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::*






|
|
|







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 © 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
# -*- 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.
#
# 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} {
    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}
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]







|
|
|









|

|







1
2
3
4
5
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 © 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} -body {
    lsort [::tcl::pkgconfig list]
} -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
# 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.
#
# 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]]

testConstraint testnrelevels [llength [info commands testnrelevels]]
testConstraint memory [llength [info commands memory]]

set lambda [list {{start 0} {stop 10}} {
    # init
    set i    $start






|










|







1
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 © 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 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
750
751
752
753
754
755
756







































































757
758
759
760
761
762
763
	C  ; # and called at level 1
    }
    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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	C  ; # and called at level 1
    }
    boom   ; # does not crash: the coro floor is a good insulator
    list
} -cleanup {
    rename boom {}; rename cc {}; rename c {}
} -result {}


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.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

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
# 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.
#
# 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]]

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 {






|
|
|










|







1
2
3
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 © 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 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
# 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
# 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::*
}








# 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 *}







|








>
>
>
>
>
>
>













>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 © 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
} -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-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}







|
>
>
>
>
|
>
>
>
>







142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
} -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} 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-3.17 {dict/list shimmering - Bug 3004007} testobj {
    set l [list p 1 p 2 q 3]
    dict get $l q
    list [llength $l] [testobj objtype $l]
} {6 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
	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 {
    set dictVar {a b c d e f g h}
    set keys {}
    set values {}
    dict for {k v} $dictVar {
	if {[llength $dictVar]} {
	    lappend keys $k
	    lappend values $v
	}
    }
    list [lsort $keys] [lsort $values]
} -cleanup {
    unset dictVar keys values k v
} -result {{a c e g} {b d f h}}
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,







|




|




|


|







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
	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} -constraints testobj -body {
    set dictVar {a b c d e f g h}
    set keys {}
    set values {}
    dict for {k v} $dictVar {
	if {[string length $dictVar]} {
	    lappend keys $k
	    lappend values $v
	}
    }
    list [lsort $keys] [lsort $values] [testobj objtype $dictVar]
} -cleanup {
    unset dictVar keys values k v
} -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,
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
        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
	    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}







|







1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
        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 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
	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 {
    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]} {
	    lappend keys $k
	    lappend values $v
	    return -level 0 $k
	}
    }]] [lsort $keys] [lsort $values]
} -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 {
    apply {{} {
	set dictVar {a b c d e f g h}
	list [dict size [dict map {k v} $dictVar {
	    if {[llength $dictVar]} {
		lappend keys $k
		lappend values $v
		return -level 0 $k
	    }
	}]] [lsort $keys] [lsort $values]
    }}
} -result {4 {a c e g} {b d f h}}
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,







|





|




|


|
|



|




|

|







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
	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} -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 {[string length $dictVar]} {
	    lappend keys $k
	    lappend values $v
	    return -level 0 $k
	}
    }]] [lsort $keys] [lsort $values] [testobj objtype $dictVar]
} -cleanup {
    unset dictVar keys values k v
} -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 {[string length $dictVar]} {
		lappend keys $k
		lappend values $v
		return -level 0 $k
	    }
	}]] [lsort $keys] [lsort $values] [testobj objtype $dictVar]
    }}
} -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
# 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.
#
# 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]]

testConstraint testdstring [llength [info commands testdstring]]
if {[testConstraint testdstring]} {
    testdstring free
}

test dstring-1.1 {appending and retrieving} -constraints testdstring -setup {






|
|
|










|







1
2
3
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 © 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 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
    # decision about whether #-quoting can be disabled.
    testdstring append "x  " -1
    testdstring element #
    testdstring get
} -cleanup {
    testdstring free
} -result {x  #}

































test dstring-3.1 {nested sublists} -constraints testdstring -setup {
    testdstring free
} -body {
    testdstring start
    testdstring element foo
    testdstring element bar







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
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
} -body {
    testdstring append "xyzzy" -1
    testdstring trunc 0
    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 {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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}}








































# cleanup
if {[testConstraint testdstring]} {
    testdstring free
}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












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
# 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.
#
# 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]
}

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 {




|
|















|



















<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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 © 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 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]]


# 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
    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] \
	[encoding convertfrom jis0208 8C]
} "8C \u4e4e"

test encoding-2.1 {Tcl_FreeEncoding: refcount == 0} {
    encoding convertto jis0208 \u4e4e
} {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
    encoding system iso8859-1
    llength shiftjis		;# Shimmer away any cache of Tcl_Encoding
    lappend x [catch {encoding convertto shiftjis \u4e4e} msg] $msg
} -cleanup {
    encoding system iso8859-1
    encoding dirs $path
    encoding system $system
} -result "\u008c\u00c1 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-4.1 {Tcl_GetEncodingNames} -constraints {testencoding} -setup {
    cd [makeDirectory tmp]
    makeDirectory [file join tmp encoding]
    set path [encoding dirs]
    encoding dirs {}
    catch {unset encodings}







|

|


|







|


|




|

















>
>
>
>
>
>
>
>







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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 ] \
	[encoding convertfrom jis0208 8C]
} "8C "

test encoding-2.1 {Tcl_FreeEncoding: refcount == 0} {
    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 ]	;# old one found
    encoding system iso8859-1
    llength shiftjis		;# Shimmer away any cache of Tcl_Encoding
    lappend x [catch {encoding convertto shiftjis } msg] $msg
} -cleanup {
    encoding system iso8859-1
    encoding dirs $path
    encoding system $system
} -result "\x8C\xC1 1 {unknown encoding \"shiftjis\"}"

test encoding-3.1 {Tcl_GetEncodingName, NULL} -setup {
    set old [encoding system]
} -body {
    encoding system shiftjis
    encoding system
} -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
    removeDirectory tmp
} -result {junk junk2}

test encoding-5.1 {Tcl_SetSystemEncoding} -setup {
    set old [encoding system]
} -body {
    encoding system jis0208
    encoding convertto \u4e4e
} -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







|







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 
} -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
    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"

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"
    close $f
    set f [open [file join [temporaryDirectory] dummy] r]
    fconfigure $f -translation binary -encoding shiftjis
    set x [read $f]
    close $f
    file delete [file join [temporaryDirectory] dummy]
    return $x
} "ab\u4e4eg"

test encoding-9.1 {Tcl_UtfToExternalDString: small buffer} {
    encoding convertto jis0208 "\u543e\u543e\u543e\u543e"
} {8c8c8c8c}
test encoding-9.2 {Tcl_UtfToExternalDString: big buffer} {
    set a \u4e4e\u4e4e\u4e4e\u4e4e\u4e4e\u4e4e\u4e4e\u4e4e
    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"
    close $f
    set f [open [file join [temporaryDirectory] dummy] r]
    fconfigure $f -translation binary -encoding iso8859-1
    set x [read $f]
    close $f
    file delete [file join [temporaryDirectory] dummy]
    return $x
} "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]
    encoding dirs $path
    encoding system $system
    lappend x [encoding convertto jis0208 \u4e4e]
} {1 {unknown encoding "jis0208"} 8C}
test encoding-11.2 {LoadEncodingFile: single-byte} {
    encoding convertfrom jis0201 \xa1
} "\uff61"
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"
test encoding-11.5 {LoadEncodingFile: escape file} {
    viewable [encoding convertto iso2022 \u4e4e]
} [viewable "\x1b\$B8C\x1b(B"]
test encoding-11.5.1 {LoadEncodingFile: escape file} {
    viewable [encoding convertto iso2022-jp \u4e4e]
} [viewable "\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
} -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"}












# 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"
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"
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"
test encoding-12.4 {LoadTableEncoding: double-byte encoding} {
    set x [encoding convertto jis0208 \u4e4e\u3b1]
    append x [encoding convertfrom jis0208 8C&A]
} "8C&A\u4e4e\u3b1"
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"

test encoding-13.1 {LoadEscapeTable} {
    viewable [set x [encoding convertto iso2022 ab\u4e4e\u68d9g]]
} [viewable "ab\x1b\$B8C\x1b\$\(DD%\x1b(Bg"]

test encoding-15.1 {UtfToUtfProc} {
    encoding convertto utf-8 \xa3
} "\xc2\xa3"
test encoding-15.2 {UtfToUtfProc null character output} testbytestring {
    binary scan [testbytestring [encoding convertto utf-8 \u0000]] 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]]
    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]
    list [string length $x] $y
} -result "6 \U1F602"
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"
test encoding-15.6 {UtfToUtfProc emoji character output} {
    set x \uDE02\uD83D\uDE02\uD83D
    set y [encoding convertto utf-8 \uDE02\uD83D\uDE02\uD83D]
    binary scan $y H* z
    list [string length $y] $z
} {10 edb882f09f9882eda0bd}
test encoding-15.7 {UtfToUtfProc emoji character output} {
    set x \uDE02\uD83D\uD83D
    set y [encoding convertto 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]
    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]
    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]
    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]
    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]
    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]
    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]
    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]
    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]
    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]
    binary scan $y H* z
    list [string length $y] $z
} {4 f09f9882}

























































test encoding-16.1 {Utf16ToUtfProc} -body {
    set val [encoding convertfrom utf-16 NN]
    list $val [format %x [scan $val %c]]
} -result "\u4E4E 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"]
    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 {
    set val [encoding convertfrom ucs-2 "\xD8\xD8\xDC\xDC"]
    list $val [format %x [scan $val %c]]
} -result "\U460DC 460dc"





























































































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.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"







test encoding-18.1 {TableToUtfProc} {

} {}
















test encoding-19.1 {TableFromUtfProc} {

} {}
















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 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
\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
\u3057\u3087\u3046\u304b\uff1f"


cd [temporaryDirectory]
set fid [open iso2022.txt w]
fconfigure $fid -encoding binary
puts -nonewline $fid $iso2022encData
close $fid








|








|




|







|


|


|













|







|
<
<
<
<
<
<
<
<
<
<
<
<







|


|


|
|


|

|
|

|
|

|
|













|








|
>
>
>
>
>
>
>
>
>
>
>



|
|
|
|

|
|
|

|
|
|

|

|

|
|
|
|


|
|


|
|

|



|





|

|




|


|


|


|




|
|





|




|
|




|
|





|





|





|





|





|



|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|





|





|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




|
|
|

|
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>

|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|
|
|
|
|


|
<
<
>
>
|
<
>







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229












230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
    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
} 吾吾吾吾
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 "

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"
    close $f
    set f [open [file join [temporaryDirectory] dummy] r]
    fconfigure $f -translation binary -encoding shiftjis
    set x [read $f]
    close $f
    file delete [file join [temporaryDirectory] dummy]
    return $x
} ab乎g

test encoding-9.1 {Tcl_UtfToExternalDString: small buffer} {
    encoding convertto jis0208 "吾吾吾吾"
} {8c8c8c8c}
test encoding-9.2 {Tcl_UtfToExternalDString: big buffer} {
    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乎g
    close $f
    set f [open [file join [temporaryDirectory] dummy] r]
    fconfigure $f -translation binary -encoding iso8859-1
    set x [read $f]
    close $f
    file delete [file join [temporaryDirectory] dummy]
    return $x
} "ab\x8C\xC1g"













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 } msg] $msg]
    encoding dirs $path
    encoding system $system
    lappend x [encoding convertto jis0208 ]
} {1 {unknown encoding "jis0208"} 8C}
test encoding-11.2 {LoadEncodingFile: single-byte} {
    encoding convertfrom jis0201 \xA1
} 
test encoding-11.3 {LoadEncodingFile: double-byte} {
    encoding convertfrom jis0208 8C
} 
test encoding-11.4 {LoadEncodingFile: multi-byte} {
    encoding convertfrom shiftjis \x8C\xC1
} 
test encoding-11.5 {LoadEncodingFile: escape file} {
    encoding convertto iso2022 
} \x1B\$B8C\x1B(B
test encoding-11.5.1 {LoadEncodingFile: escape file} {
    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 
} -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 Ġ]
    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Ġ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 abg]
    append x [encoding convertfrom shiftjis ab\x8C\xC1g]
} "ab\x8C\xC1gabg"
test encoding-12.4 {LoadTableEncoding: double-byte encoding} {
    set x [encoding convertto jis0208 乎α]
    append x [encoding convertfrom jis0208 8C&A]
} "8C&A乎α"
test encoding-12.5 {LoadTableEncoding: symbol encoding} {
    set x [encoding convertto symbol γ]
    append x [encoding convertto symbol g]
    append x [encoding convertfrom symbol g]
} "ggγ"

test encoding-13.1 {LoadEscapeTable} {
    encoding convertto iso2022 ab乎棙g
} ab\x1B\$B8C\x1B\$\(DD%\x1B(Bg

test encoding-15.1 {UtfToUtfProc} {
    encoding convertto utf-8 £
} "\xC2\xA3"
test encoding-15.2 {UtfToUtfProc null character output} testbytestring {
    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 \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 -profile tcl8 utf-8 \xED\xA0\xBD\xED\xB8\x82]
    list [string length $x] $y
} -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 😂"
test encoding-15.6 {UtfToUtfProc emoji character output} {
    set x \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
} {12 edb882eda0bdedb882eda0bd}
test encoding-15.7 {UtfToUtfProc emoji character output} {
    set x \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é
    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 -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é
    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é
    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 -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 -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 -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 -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 -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 😂
    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-16.1 {Utf16ToUtfProc} -body {
    set val [encoding convertfrom utf-16 NN]
    list $val [format %x [scan $val %c]]
} -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 -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 " 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 {UtfToUcs2Proc} -body {
    encoding convertfrom utf-16 \xD8\xD8\xDC\xDC
} -result "\U460DC"
test encoding-17.3 {UtfToUtf16Proc} -body {
    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 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} -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 "\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 "私どもでは、チップご購入時にご登録いただいたご住所をキャッシュアウトの際の


小切手送付先として使用しております。恐れ入りますが、正しい住所をご登録しなお
お願いいたします。また、大変恐縮ですが、住所変更のあと、日本語サービス部(
casino_japanese@___.com )までご住所変更済の連絡をいただけないで

しょうか?"

cd [temporaryDirectory]
set fid [open iso2022.txt w]
fconfigure $fid -encoding binary
puts -nonewline $fid $iso2022encData
close $fid

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
	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 {
	encoding system cp1252;	# Bug #2891556 crash revelator
	fconfigure stdout -encoding iso2022-jp
	puts ab\u4e4e\u68d9g
	set env(TCL_FINALIZE_ON_EXIT) 1
	exit
    }]

} "ab\x1b\$B8C\x1b\$(DD%\x1b(Bg (ab\\u001b\$B8C\\u001b\$(DD%\\u001b(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
	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)"]




test encoding-24.4 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xc0\x80"]
} 1
test encoding-24.5 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xc0\x81"]
} 2
test encoding-24.6 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xc1\xbf"]
} 2
test encoding-24.7 {Parse valid or invalid utf-8} {
    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"]
} 3
test encoding-24.9 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom 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"]
} 1
test encoding-24.11 {Parse valid or invalid utf-8} {
    string length [encoding convertfrom utf-8 "\xef\xbf\xbf"]
} 1






















































































































file delete [file join [temporaryDirectory] iso2022.txt]

#
# Begin jajp encoding round-trip conformity tests
#
proc foreach-jisx0208 {varName command} {







|


|


<
>
|





|







|
|

>
>
>
|
|
|

|


|


|


|


|


|


|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	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
    runInSubprocess {
	encoding system cp1252;	# Bug #2891556 crash revelator
	fconfigure stdout -encoding iso2022-jp
	puts ab乎棙g
	set env(TCL_FINALIZE_ON_EXIT) 1
	exit

    }
} "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 "乎乞也"; # 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 $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.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 -profile tcl8 utf-8 "\xC0\x81"]
} 2
test encoding-24.6 {Parse valid or invalid utf-8} {
    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"]
} 1
test encoding-24.8 {Parse valid or invalid utf-8} {
    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 -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"]
} 1
test encoding-24.11 {Parse valid or invalid utf-8} {
    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
	} else {
	    error "really?"
	}
    }
}
proc gen-jisx0208-euc-jp {code} {
    binary format cc \
	[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"
}
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))}]
    } else {
	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} {







|



|





|
|

|







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
	} else {
	    error "really?"
	}
    }
}
proc gen-jisx0208-euc-jp {code} {
    binary format cc \
	[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"
}
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))}]
    } else {
	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} {
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
	} -cleanup {
	    close $fa
	    close $fb
	} -result {}
    }
}

test encoding-26.0 {Tcl_GetEncodingSearchPath} -constraints {
    testgetencpath
} -setup {
    set origPath [testgetencpath]
    testsetencpath slappy
} -body {
    testgetencpath
} -cleanup {
    testsetencpath $origPath
} -result slappy

file delete {*}[glob -directory [temporaryDirectory] *.chars *.tcltestout]
# ===> Cut here <===

# EscapeFreeProc, GetTableEncoding, unilen are fully tested by the rest of
# this file.







|
<
<
|
|

|

|







1024
1025
1026
1027
1028
1029
1030
1031


1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
	} -cleanup {
	    close $fa
	    close $fb
	} -result {}
    }
}

test encoding-26.0 {Tcl_GetEncodingSearchPath} -setup {


    set origPath [encoding dirs]
    encoding dirs slappy
} -body {
    encoding dirs
} -cleanup {
    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

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

		# discard the cached internal representation of Tcl_Encoding
		# Unfortunately, without this, encoding 2-1 fails.
		llength $name
	}
	return $count
} -result 85

runtests







}




































































































# cleanup
namespace delete ::tcl::test::encoding
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|






|



>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









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

test encoding-28.0 {all encodings load} -body {
	set string hello
	foreach name [encoding names] {
		if {$name ne "unicode"} {
		    incr count
		}
		encoding convertto -profile tcl8 $name $string

		# discard the cached internal representation of Tcl_Encoding
		# Unfortunately, without this, encoding 2-1 fails.
		llength $name
	}
	return $count
} -result 93

runtests

test encoding-bug-183a1adcc0-1 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
    testencoding
} -body {
    # Note - buffers are initialized to \xFF
    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



# 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
# 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.
#
# 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


# [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"} {






|
|
|









|
|
>
>
|
>







1
2
3
4
5
6
7
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 © 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::*
}

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
    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
    __CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM
    CommonProgramFiles CommonProgramFiles(x86) ProgramFiles
    ProgramFiles(x86) CommonProgramW6432 ProgramW6432

    WINECONFIGDIR WINEDATADIR WINEDLLDIR0 WINEHOMEDIR
}

variable printenvScript [makeFile [string map [list @keep@ [list $keep]] {
    encoding system iso8859-1
    proc lrem {listname name} {
	upvar $listname list







|



>







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 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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
    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:
    encodingswitch cp1252
    # 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







|

|







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:
    encodingswitch cp1252
    # 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
} -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
    # 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








|







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 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
} -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.
    # 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







|







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 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
407
408
409
410
411
412
413
414


















































415
416
417
418
419
420
421
422
423























































424
425
426
427
428
429
430
      }
      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-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}


























































# cleanup
rename getenv {}
rename envrestore {}
rename envprep {}
rename encodingrestore {}
rename encodingswitch {}







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
      }
      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
# 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.
#
# 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::*






|
|
|







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 © 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::*
347
348
349
350
351
352
353







354
355
356
357
358
359
360
} {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}








# 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} {







>
>
>
>
>
>
>







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
	} finally {
	    throw BAR baz
	}
    }
    list $em [dict get $opts -errorcode]
} {bar FOO}

# try tests - fallthough 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} {







|







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 - 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
# 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.
#
# 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::*






|
|
|







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 © 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
    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
    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
    set dummy($cmd) $cmd
    set dummy($cmd2) $cmd2
    unset dummy
    eval $cmd $cmd2
} {1 2 3 4 5}

# cleanup







|







|







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 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 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
# 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.
#
# 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]
}


testConstraint testfilehandler [llength [info commands testfilehandler]]
testConstraint testexithandler [llength [info commands testexithandler]]
testConstraint testfilewait [llength [info commands testfilewait]]
testConstraint exec [llength [info commands exec]]





|
|









|
|







1
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 © 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 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
    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
# 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} {







|







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, 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} {
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
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]
} {1 {child process exited abnormally} CHILDSTATUS 3}

test event-11.1 {Tcl_VwaitCmd procedure} -returnCodes error -body {
    vwait
} -result {wrong # args: should be "vwait name"}
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 {







|

|
<
<
<







505
506
507
508
509
510
511
512
513
514



515
516
517
518
519
520
521
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]
} {1 {child process exited abnormally} CHILDSTATUS 3}

test event-11.1 {Tcl_VwaitCmd procedure} -body {
    vwait
} -result {}



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 {

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
# 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.
#
# 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::*
}

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)]}]

unset -nocomplain path

# 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






|
|
|











|
<
<
<

<
<
<
>
|



|







1
2
3
4
5
6
7
8
9
10
11
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 © 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]







# 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.
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
	    continue
	}
	lappend newcmd $arg
    }
    exit
} sh2]
set path(sleep) [makeFile {
    after [expr $argv*1000]
    exit
} sleep]
set path(exit) [makeFile {
    exit $argv
} exit]

proc readfile filename {







|







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}]
    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
    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
	return [subst -novariables $s]
    }
} -constraints {exec} -body {
    # If this fails, it may give back: "\uC3\uA9\uC3\uA0\uC3\uBC\uC3\uB1"
    # 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"]
} -cleanup {
    encoding system $sysenc
    rename quotenonascii {}
} -result {\u00e9\u00e0\u00fc\u00f1}

# 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} {







|
|



|


|



|







159
160
161
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 "\[\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: "\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) << "\xE9\xE0\xFC\xF1"]
} -cleanup {
    encoding system $sysenc
    rename quotenonascii {}
} -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
} -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 {
    exec ~non_existent_user/foo/bar






} -returnCodes error -result {user "non_existent_user" doesn't exist}
test exec-10.21 {errors in exec invocation} -constraints {exec notValgrind} -body {
    exec [interpreter] true | ~xyzzy_bad_user/x | false
} -returnCodes error -result {user "xyzzy_bad_user" doesn't exist}
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}
# 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 {







|

>
>
>
>
>
>
|
|

|


|







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.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 {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 {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 {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 {
669
670
671
672
673
674
675


676
677
678
679
680
681
682
683
} -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...


test exec-19.1 {exec >> uses O_APPEND} -constraints {exec unix notValgrind noosx} -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 \







>
>
|







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 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
    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\""






























# ----------------------------------------------------------------------
# cleanup

foreach file {gorp.file gorp.file2 echo echo2 cat wc sh sh2 sleep exit err} {
    removeFile $file
}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
# 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.
#
# 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 {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 }
}











|
|










|













<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 © 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 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 testexprlongobj [llength [info commands testexprlongobj]]


if {[namespace which -command testbumpinterpepoch] eq ""} {
  proc testbumpinterpepoch {} { rename ::set ::dummy; rename ::dummy ::set }
}

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
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
} 45097156608
test execute-7.12 {Wide int handling in INST_LSHIFT} {
    expr 12345678901<<3
} 98765431208
test execute-7.13 {Wide int handling in INST_RSHIFT} {
    expr 0x543210febcda9876>>7
} 47397893236700464
test execute-7.14 {Wide int handling in INST_RSHIFT} {
    expr wide(0x9876543210febcda)>>7
} -58286587177206407
test execute-7.15 {Wide int handling in INST_BITOR} {
    expr wide(0x9876543210febcda) | 0x543210febcda9876
} -2560765885044310786
test execute-7.16 {Wide int handling in INST_BITXOR} {
    expr wide(0x9876543210febcda) ^ 0x543210febcda9876
} -3727778945703861076
test execute-7.17 {Wide int handling in INST_BITAND} {
    expr wide(0x9876543210febcda) & 0x543210febcda9876
} 1167013060659550290
test execute-7.18 {Wide int handling in INST_ADD} {
    expr wide(0x7fffffff)+wide(0x7fffffff)
} 4294967294
test execute-7.19 {Wide int handling in INST_ADD} {
    expr 0x7fffffff+wide(0x7fffffff)
} 4294967294
test execute-7.20 {Wide int handling in INST_ADD} {
    expr wide(0x7fffffff)+0x7fffffff
} 4294967294
test execute-7.21 {Wide int handling in INST_ADD} {
    expr double(0x7fffffff)+wide(0x7fffffff)
} 4294967294.0
test execute-7.22 {Wide int handling in INST_ADD} {
    expr wide(0x7fffffff)+double(0x7fffffff)
} 4294967294.0
test execute-7.23 {Wide int handling in INST_SUB} {
    expr 0x123456789a-0x20406080a
} 69530054800
test execute-7.24 {Wide int handling in INST_MULT} {
    expr 0x123456789a*193
} 15090186251290
test execute-7.25 {Wide int handling in INST_DIV} {
    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







|


|


|


|


|


|


|


|


|


|


|


|


|


|


|







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}
} 45097156608
test execute-7.12 {Wide int handling in INST_LSHIFT} {
    expr {12345678901 << 3}
} 98765431208
test execute-7.13 {Wide int handling in INST_RSHIFT} {
    expr {0x543210febcda9876 >> 7}
} 47397893236700464
test execute-7.14 {Wide int handling in INST_RSHIFT} {
    expr {wide(0x9876543210febcda) >> 7}
} -58286587177206407
test execute-7.15 {Wide int handling in INST_BITOR} {
    expr {wide(0x9876543210febcda) | 0x543210febcda9876}
} -2560765885044310786
test execute-7.16 {Wide int handling in INST_BITXOR} {
    expr {wide(0x9876543210febcda) ^ 0x543210febcda9876}
} -3727778945703861076
test execute-7.17 {Wide int handling in INST_BITAND} {
    expr {wide(0x9876543210febcda) & 0x543210febcda9876}
} 1167013060659550290
test execute-7.18 {Wide int handling in INST_ADD} {
    expr {wide(0x7fffffff) + wide(0x7fffffff)}
} 4294967294
test execute-7.19 {Wide int handling in INST_ADD} {
    expr {0x7fffffff + wide(0x7fffffff)}
} 4294967294
test execute-7.20 {Wide int handling in INST_ADD} {
    expr {wide(0x7fffffff) + 0x7fffffff}
} 4294967294
test execute-7.21 {Wide int handling in INST_ADD} {
    expr {double(0x7fffffff) + wide(0x7fffffff)}
} 4294967294.0
test execute-7.22 {Wide int handling in INST_ADD} {
    expr {wide(0x7fffffff) + double(0x7fffffff)}
} 4294967294.0
test execute-7.23 {Wide int handling in INST_SUB} {
    expr {0x123456789a - 0x20406080a}
} 69530054800
test execute-7.24 {Wide int handling in INST_MULT} {
    expr {0x123456789a * 193}
} 15090186251290
test execute-7.25 {Wide int handling in INST_DIV} {
    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
    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]]
	::tcltest::loadTestedCommands
	if {[namespace which -command testbumpinterpepoch] eq ""} {
	  proc testbumpinterpepoch {} { rename ::set ::dummy; rename ::dummy ::set }
	}
    }
} -body {
    child eval {







|







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 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
} -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]]
	::tcltest::loadTestedCommands
	if {[namespace which -command testbumpinterpepoch] eq ""} {
	  proc testbumpinterpepoch {} { rename ::set ::dummy; rename ::dummy ::set }
	}
    }
} -body {
    set res {}







|







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 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
    } 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
} {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} ;#}







|







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 [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
# 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.
#
# 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]]

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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 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
51
52
53
54
55
56
57
58
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 © 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 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}]


# 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
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#
} -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 "/"}}







|







519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
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`
} -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 "/"}}

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
# 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.
#
# 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
		ieeeValues(NaN)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    binary scan \xff\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 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
51
52
53
54
55
56
57
58
59
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 © 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 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
		ieeeValues(NaN)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    binary scan \xFF\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
    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.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} {







|
|
|







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} -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
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 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 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 {







|




|







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 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 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 {
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
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.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 {







|







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 \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 {
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
       upvar 1 $name var
       if {[incr counter] % 2 == 1} {
           set var "$counter oops [concat $extraargs]"
       } else {
           set var "$counter + [concat $extraargs]"
       }
    }
    trace variable exprtracevar r [list exprtraceproc 10]
    list [catch {expr "$exprtracevar + 20"} a] $a \
        [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]







|







773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
       upvar 1 $name var
       if {[incr counter] % 2 == 1} {
           set var "$counter oops [concat $extraargs]"
       } else {
           set var "$counter + [concat $extraargs]"
       }
    }
    trace add variable exprtracevar read [list exprtraceproc 10]
    list [catch {expr "$exprtracevar + 20"} a] $a \
        [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]
1423
1424
1425
1426
1427
1428
1429


1430
1431
1432
1433
1434
1435
1436
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



# 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







>
>







1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
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
6694
6695
6696
6697
6698
6699
6700






6701
6702
6703
6704
6705
6706
6707
} { 	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







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}







>
>
>
>
>
>







6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
} { 	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}
7379
7380
7381
7382
7383
7384
7385
7386





































































































7387
7388
7389
7390

7391
7392
7393
7394
7395
7396
    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






































































































# cleanup
unset -nocomplain a
unset -nocomplain min
unset -nocomplain max

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>






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
    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
# 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.
#
# 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]]

cd [temporaryDirectory]

testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testchmod [llength [info commands testchmod]]
testConstraint winVista 0
testConstraint winXP 0
# Don't know how to determine this constraint correctly
testConstraint notNetworkFilesystem 0
testConstraint reg 0
if {[testConstraint win]} {
    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


    }
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]





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 {






|
|










|





|
<




|










>
>


|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
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 © 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 tcl::test [info patchlevel]]

cd [temporaryDirectory]

testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testchmod [llength [info commands testchmod]]
testConstraint winLessThan10 0

# Don't know how to determine this constraint correctly
testConstraint notNetworkFilesystem 0
testConstraint reg 0
if {[testConstraint win]} {
    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 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

    if {[catch {makeDirectory tcl[pid] /tmp} tmpspace] == 0} {
	testConstraint xdev [expr {([dev .] != [dev $tmpspace])}]
    }
}

# Also used in winFCmd...
if {[testConstraint win]} {
    if {$::tcl_platform(osVersion) >= 5.0} {
	testConstraint winVista 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 fileSharing 0
testConstraint notFileSharing 1
testConstraint linkFile 1
testConstraint linkDirectory 1

# 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"
    }
}
















































proc createfile {file {string a}} {
    set f [open $file w]
    puts -nonewline $f $string
    close $f
    return $string
}







|
<
|
<
<
<








>






|














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







66
67
68
69
70
71
72
73

74



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

    if {[catch {makeDirectory tcl[pid] /tmp} tmpspace] == 0} {
	testConstraint xdev [expr {([dev .] != [dev $tmpspace])}]
    }
}

# Also used in winFCmd...
if {[testConstraint win] && $::tcl_platform(osVersion) < 10.0} {

    testConstraint winLessThan10 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

# 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
    } on error {} {
	return 0
    }
    return [string match $matchString $fileString]
}

proc openup {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*]
	}
	foreach file $x {




	    if {
		[catch {file delete -force -- $file}]
		&& [testConstraint testchmod]
	    } then {
		catch {openup $file}
		catch {file delete -force -- $file}
	    }







>
>
>
>















|


>
>
>
>







171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
    } 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* ~*]
	}
	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
test fCmd-1.1 {TclFileRenameCmd} -constraints {notRoot} -setup {
    cleanup
} -body {
    createfile tf1
    file rename tf1 tf2
    glob tf*
} -result {tf2}






































test fCmd-2.1 {TclFileCopyCmd} -constraints {notRoot} -setup {
    cleanup
} -body {
    createfile tf1
    file copy tf1 tf2
    lsort [glob tf*]
} -result {tf1 tf2}





































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}
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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
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 {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
	[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 {
    cleanup
} -constraints {notRoot unixOrWin} -returnCodes error -body {
    file mkdir td1
    file rename / td1
} -result {error renaming "/" to "td1": file already 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}]

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 {
    cleanup
} -constraints {notRoot} -returnCodes error -body {





    file mkdir ~_totally_bogus_user

} -result {user "_totally_bogus_user" doesn't exist}
test fCmd-4.5 {TclFileMakeDirsCmd: Tcl_SplitPath returns 0: *name == '\0'} -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 {







|
|




|










|




















|

|
>
>
>
>
>

>
|
|







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
	[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 {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 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 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 treats ~ as normal char} -setup {
    cleanup
} -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 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
    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}]
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 {
    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 {
    file mkdir foo
    file attr foo -perm 040000
    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}

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 {}







|










|

















|

|









|







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
    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 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 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 notWsl} -body {
    file mkdir foo
    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

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
} -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 fails} -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 {
    catch {file delete ~/tf1}
} -constraints {notRoot} -body {
    createfile ~/tf1
    file delete ~/tf1
} -result {}
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}







>
>
|

|
>
|
<


<
|







556
557
558
559
560
561
562
563
564
565
566
567
568
569

570
571

572
573
574
575
576
577
578
579
} -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
} -constraints {notRoot} -body {
    file delete ~_totally_bogus_user
} -result {}
test fCmd-5.7 {
    TclFileDeleteCmd: Tcl_TranslateFileName treats ~ as normal char

} -constraints {notRoot} -body {
    createfile ~/tf1

} -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
} -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 {
    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}
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}
test fCmd-6.12 {CopyRenameOneFile: force != 0} -setup {
    cleanup
} -constraints {notRoot} -body {
    createfile tf1
    createfile tf2
    file rename -force tf1 tf2
    glob tf*







|




















|






|







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
} -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 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 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 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
} -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 {
    file mkdir td1/td2/td3
    file attributes td1 -permissions 0000
    file rename td1 $tmpspace
} -returnCodes error -cleanup {
    file attributes td1 -permissions 0755
    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
} -returnCodes error -cleanup {
    file attributes $td1name -permissions 0755
    file delete -force ~/td1
} -result {error copying "~/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
} -returnCodes error -cleanup {
    file attributes $td1name -permissions 0755
    file delete -force ~/td1
} -result {error copying "td2" to "~/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
} -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"
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}
test fCmd-6.28 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
    cleanup $tmpspace
} -constraints {notRoot xdev} -body {
    file mkdir td1/td2/td3
    file attributes td1/td2/td3 -permissions 0000
    file rename td1 $tmpspace
} -returnCodes error -cleanup {
    file attributes td1/td2/td3 -permissions 0755
    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 {
    file mkdir foo/bar
    file attr foo -perm 040555
    file rename foo/bar $tmpspace
} -returnCodes error -cleanup {
    catch {file delete [file join $tmpspace bar]}
    catch {file attr foo -perm 040777}
    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]







|

|


|





|
|
|
|

|
|
|




|
|
|
|

|
|
|



|
|
|
|

|
|
|







|


|

|


|











|

|



|







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
} -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 notWsl} -body {
    file mkdir td1/td2/td3
    file attributes td1 -permissions 0
    file rename td1 $tmpspace
} -returnCodes error -cleanup {
    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 [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 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 [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 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 [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 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 exists}
test fCmd-6.28 {CopyRenameOneFile: TclpCopyDirectory failed} -setup {
    cleanup $tmpspace
} -constraints {notRoot xdev notWsl} -body {
    file mkdir td1/td2/td3
    file attributes td1/td2/td3 -permissions 0
    file rename td1 $tmpspace
} -returnCodes error -cleanup {
    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 notWsl} -body {
    file mkdir foo/bar
    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 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
} -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 {
    createfile --
    createfile -force
    file delete -force -force -- -- -force
    glob -- -- -force
} -result {no files matched glob patterns "-- -force"}

test fCmd-8.1 {FileBasename: basename of ~user: argc == 1 && *path == ~} \
    -constraints {unix notRoot knownBug} -body {
    # Labelled knownBug because it is dangerous [Bug: 3881]
    file mkdir td1
    file attr td1 -perm 040000
    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
test fCmd-8.3 {file copy and path translation: ensure correct error} -body {
    file copy ~ [file join this file doesnt exist]
} -returnCodes error -result [subst \
	{error copying "~" 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 {
    file mkdir td1
    file mkdir td2
    file attr td2 -perm 040000
    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 {
    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 {
    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 {
    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 {
    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}







|




|


|
|

|







|

|

|



|


|




















|

<
<
<
<
<
<
<
<
<
<
<
|


















|

<
<
<
<
<
<
<
<
<
<
|







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
} -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} -body {
    createfile --
    createfile -force
    file delete -force -force -- -- -force
    glob -- -- -force
} -result {}

test fCmd-8.1 {FileBasename: basename of ~user: argc == 1 && *path == ~} \
    -constraints {unix notRoot knownBug tildeexpansion} -body {
    # Labeled knownBug because it is dangerous [Bug: 3881]
    file mkdir td1
    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 1
test fCmd-8.3 {file copy and path translation: ensure correct error} -body {
    file copy [file home] [file join this file doesnt exist]
} -returnCodes error -result [subst \
   {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 notWsl} -body {
    file mkdir td1
    file mkdir td2
    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 {file rename: comprehensive: dir to new name} -setup {
    cleanup











} -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 {file rename: comprehensive: dir to self} -setup {
    cleanup










} -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
    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}
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
    # into another directory.
    file mkdir td1
    file mkdir [file join td2 td1]
    file mkdir tds1
    file mkdir tds2
    file mkdir tds3
    file mkdir tds4







|



|







975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
    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 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
    # 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
	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}]
# 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
    } 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*]] \
    [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}]
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
    } 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}}]
# 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 \







|








<
<
<


<
|
<
<
<












|

|






<
<
<


<
|
<
<
<














|







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
	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 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]



    set a1 [list [catch {file rename -force tds1 tdd1} msg] $msg]
    set a2 [list [catch {file rename -force tds2 tdd2} msg] $msg]

    set w2 0



    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 [glob tf*] [lsort [glob -directory td1 t*]] \
    [file writable [file join td1 tf3]] [file writable [file join td1 tf4]]
} -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



    file rename td1 [file join td3 td3]
    file rename td2 [file join td3 td4]

    set w4 0



    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 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
    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 {
    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

    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







|


















>







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
    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 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
    createfile tfs2
    createfile tfs3
    createfile tfs4
    createfile tfd1
    createfile tfd2
    createfile tfd3
    createfile 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}
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







>
>
>
>
>
>
>
>
|
|
|
|
>






|







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
    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
    }
    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 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
    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}]
test fCmd-10.6 {file copy: comprehensive: dir to non-empty dir} -setup {
    cleanup
} -constraints {notRoot unixOrWin testchmod} -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}]
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 {
    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*]] \







|


|








|














|







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
    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 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 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 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 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
} -constraints {notRoot} -body {
    createfile tfa1
    createfile tfa2
    createfile tfa3
    catch {file rename tfa1 tfa2 tfa3}
} -cleanup {
    file delete tfa1 tfa2 tfa3
} -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]







|







1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
} -constraints {notRoot} -body {
    createfile tfa1
    createfile tfa2
    createfile tfa3
    catch {file rename tfa1 tfa2 tfa3}
} -cleanup {
    file delete tfa1 tfa2 tfa3
} -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
    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    catch {file rename ~/tfa1 tfa2}
} -cleanup {
    set ::env(HOME) $temp
} -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}
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}







|











|







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
    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    catch {file rename ~/tfa1 tfa2}
} -cleanup {
    set ::env(HOME) $temp
} -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
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
    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}
test fCmd-12.8 {renamefile: generic error} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
    file mkdir tfa
    file mkdir tfa/dir
    file attributes tfa -permissions 0555
    catch {file rename tfa/dir tfa2}
} -cleanup {
    catch {file attributes tfa -permissions 0777}
    file delete -force tfa
} -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 {







|


|


|


|

|







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
    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
test fCmd-12.8 {renamefile: generic error} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot notWsl} -body {
    file mkdir tfa
    file mkdir tfa/dir
    file attributes tfa -permissions 0o555
    catch {file rename tfa/dir tfa2}
} -cleanup {
    catch {file attributes tfa -permissions 0o777}
    file delete -force tfa
} -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
    set temp $::env(HOME)
} -body {
    global env
    unset env(HOME)
    catch { file copy tfa ~/foobar }
} -cleanup {
    set ::env(HOME) $temp
} -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}
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]







|









|







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
    set temp $::env(HOME)
} -body {
    global env
    unset env(HOME)
    catch { file copy tfa ~/foobar }
} -cleanup {
    set ::env(HOME) $temp
} -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
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
    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    catch {file copy ~/tfa1 tfa2}
} -cleanup {
    set ::env(HOME) $temp
} -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







|







1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    catch {file copy ~/tfa1 tfa2}
} -cleanup {
    set ::env(HOME) $temp
} -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
    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 {
    file mkdir tfa/dir/a/b/c
    file attributes tfa/dir -permissions 0000
    catch {file copy tfa tfa2}
} -cleanup {
    file attributes tfa/dir -permissions 0777
    file delete -force tfa tfa2
} -result {1}

#
# Coverage tests for TclMkdirCmd()
#


test fCmd-15.1 {TclMakeDirsCmd: target filename translation failing} -setup {
    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    catch {file mkdir ~/tfa}
} -cleanup {
    set ::env(HOME) $temp
} -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}
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
    catch {file mkdir tfa/file}
} -cleanup {
    file attributes tfa -permissions 0777
    file delete -force tfa
} -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}
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 {







|

|


|

|




>
>


|





|










|













|


|

|







|







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
    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 notWsl} -body {
    file mkdir tfa/dir/a/b/c
    file attributes tfa/dir -permissions 0
    catch {file copy tfa tfa2}
} -cleanup {
    file attributes tfa/dir -permissions 0o777
    file delete -force tfa tfa2
} -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 TODO} -body {
    global env
    unset env(HOME)
    catch {file mkdir ~/tfa}
} -cleanup {
    set ::env(HOME) $temp
} -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
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 0
    catch {file mkdir tfa/file}
} -cleanup {
    file attributes tfa -permissions 0o777
    file delete -force tfa
} -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
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
} -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}

# 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







|







1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
} -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

# 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
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}
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 {}

test fCmd-16.6 {delete: source filename translation failing} -setup {
    set temp $::env(HOME)
} -constraints {notRoot} -body {
    global env
    unset env(HOME)
    catch {file delete ~/tfa}
} -cleanup {
    set ::env(HOME) $temp
} -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}
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}
test fCmd-16.9 {error while deleting file} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot} -body {
    file mkdir tfa
    createfile tfa/a
    file attributes tfa -permissions 0555
    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 delete -force tfa
} -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 {
     file mkdir tfa1
     file attributes tfa1 -permissions 0555
     catch {file mkdir tfa1/tfa2}
} -cleanup {
     file attributes tfa1 -permissions 0777
     file delete -force tfa1
} -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}

#
# Functionality tests for TclFileRenameCmd()
#
test fCmd-18.1 {TclFileRenameCmd: rename (first form) in the same directory} \
	-setup {
    catch {file delete -force -- tfad}







|






>


|





|








|








|


|


|







|

|

















|

|


|

|
















|







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
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
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 TODO} -body {
    global env
    unset env(HOME)
    catch {file delete ~/tfa}
} -cleanup {
    set ::env(HOME) $temp
} -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
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
test fCmd-16.9 {error while deleting file} -setup {
    catch {file delete -force -- tfa}
} -constraints {unix notRoot notWsl} -body {
    file mkdir tfa
    createfile tfa/a
    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 0o777
    file delete -force tfa
} -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 notWsl} -body {
     file mkdir tfa1
     file attributes tfa1 -permissions 0o555
     catch {file mkdir tfa1/tfa2}
} -cleanup {
     file attributes tfa1 -permissions 0o777
     file delete -force tfa1
} -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

#
# 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
    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}
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







|







1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
    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
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
} -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 {
    file mkdir tfa
    file mkdir tfa/a
    file attributes tfa -permissions 0555
    catch {file delete tfa/a}
} -cleanup {
    file attributes tfa -permissions 0777
    file delete -force tfa
} -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 {
    file mkdir tfa
    file mkdir tfa/a
    file attributes tfa/a -permissions 0000
    catch {file delete -force tfa}
} -cleanup {
    file attributes tfa/a -permissions 0777
    file delete -force tfa
} -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
    }







|


|


|

|



















|


|


|

|







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
} -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 notWsl} -body {
    file mkdir tfa
    file mkdir tfa/a
    file attributes tfa -permissions 0o555
    catch {file delete tfa/a}
} -cleanup {
    file attributes tfa -permissions 0o777
    file delete -force tfa
} -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 notWsl} -body {
    file mkdir tfa
    file mkdir tfa/a
    file attributes tfa/a -permissions 00000
    catch {file delete -force tfa}
} -cleanup {
    file attributes tfa/a -permissions 0o777
    file delete -force tfa
} -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
} -constraints {notRoot} -body {
    createfile tfa1
    createfile tfa2
    createfile tfa3
    catch {file copy tfa1 tfa2 tfa3}
} -cleanup {
    file delete tfa1 tfa2 tfa3
} -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







|







2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
} -constraints {notRoot} -body {
    createfile tfa1
    createfile tfa2
    createfile tfa3
    catch {file copy tfa1 tfa2 tfa3}
} -cleanup {
    file delete tfa1 tfa2 tfa3
} -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
    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}
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 {







|







2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
    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
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
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}
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 {







|







2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
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 {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
} -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}
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}

test fCmd-28.8 {file link} -constraints {linkFile win} -setup {
    cd [temporaryDirectory]
} -body {
    file link -symbolic abc.link abc.file
} -returnCodes error -cleanup {

    cd [workingDirectory]
} -result {could not create new link "abc.link" pointing to "abc.file": not a directory}
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]







|







>
|



|
>

|







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
} -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": 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 winLessThan10} -setup {
    cd [temporaryDirectory]
} -body {
    file link -symbolic abc.link abc.file
} -cleanup {
    file delete -force abc.link
    cd [workingDirectory]
} -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
    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
    # 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]\"\







|







2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
    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
    # 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]\"\
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
} -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 {
    set r {}
    if {[info exists env(SystemDrive)]} {
        set path $env(SystemDrive)/pagefile.sys
        lappend r exists [file exists $path]
        lappend r readable [file readable $path]
        lappend r stat [catch {file stat $path a} e] $e
    }
    return $r
} -result {exists 1 readable 0 stat 0 {}}













































































































































# cleanup
cleanup
if {[testConstraint unix]} {
    removeDirectory tcl[pid] /tmp
}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:







|
>
>
|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













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
} -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
# 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
    }
    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)]

test fCmd-32.1 {file tildeexpand ~} -body {
    file tildeexpand ~
} -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.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.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.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.6 {file tildeexpand ~UNKNOWNUSER} -body {
    file tildeexpand ~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.8 {file tildeexpand ~/path} -body {
    file tildeexpand ~/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.10 {file tildeexpand ~UNKNOWNUSER} -body {
    file tildeexpand ~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.12 {file tildeexpand /~user/path} -body {
    file tildeexpand /~$::tcl_platform(user)/foo
} -result /~$::tcl_platform(user)/foo
test fCmd-32.13 {file tildeexpand ./~} -body {
    file tildeexpand ./~
} -result ./~
test fCmd-32.14 {file tildeexpand relative/path} -body {
    file tildeexpand 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.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.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)]


# 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
# 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.
#
# 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]]


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)]}]
# 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}
}}}






|
|











|
>













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 © 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 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 {![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
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
test filename-1.6 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype ~/foo
} absolute
test filename-1.7 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype ~foo
} absolute
test filename-1.8 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype ./~foo
} relative

test filename-3.1 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows







|



|



|







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 ~
} relative
test filename-1.6 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype ~/foo
} relative
test filename-1.7 {Tcl_GetPathType: unix} {testsetplatform} {
    testsetplatform unix
    file pathtype ~foo
} 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
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
test filename-3.14 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype ~
} absolute
test filename-3.15 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype ~/foo
} absolute
test filename-3.16 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype ./~foo
} relative

test filename-4.1 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix







|



|



|







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
} relative
test filename-3.14 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype ~
} relative
test filename-3.15 {Tcl_GetPathType: windows} {testsetplatform} {
    testsetplatform windows
    file pathtype ~/foo
} 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
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"
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}
test filename-4.17 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split ~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
}







|











|



|







198
199
200
201
202
203
204
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"
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}
test filename-4.17 {Tcl_SplitPath: unix} {testsetplatform} {
    testsetplatform unix
    file split ~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
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}
test filename-6.28 {Tcl_SplitPath: win} {testsetplatform} {
    testsetplatform win
    file split ~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}

test filename-7.1 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join / a
} {/a}
test filename-7.2 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix







|



|







|







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}
test filename-6.28 {Tcl_SplitPath: win} {testsetplatform} {
    testsetplatform win
    file split ~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}

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
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}
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}
test filename-7.14 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join ./~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}
test filename-7.17 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join //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

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







|







|



|







|



|






|







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
} {~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
} {./~a/~b}
test filename-7.14 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join ./~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}
test filename-7.17 {Tcl_JoinPath: unix} {testsetplatform} {
    testsetplatform unix
    file join //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

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
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}
test filename-9.12 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join / ~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







|



|







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}
test filename-9.12 {Tcl_JoinPath: win} {testsetplatform} {
    testsetplatform win
    file join / ~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
    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}
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 {
    set env(HOME) $temp
} -result {couldn't find HOME environment variable to expand path}
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}
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}
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}
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}
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}
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 {
    testtranslatefilename ~blorp/foo
} -constraints {testtranslatefilename testtranslatefilename} \
    -result {user "blorp" doesn't exist}
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}
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 {
    glob
} -result {no files matched glob patterns ""}
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 {
    glob ~xyqrszzz
} -result {user "xyqrszzz" doesn't exist}
test filename-11.7 {Tcl_GlobCmd} -returnCodes error -body {
    glob -- -nocomplain
} -result {no files matched glob pattern "-nocomplain"}
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}
test filename-11.10 {Tcl_GlobCmd} -constraints {testsetplatform} -body {
    testsetplatform unix
    glob -nocomplain ~\\xyqrszzz/bar
} -returnCodes error -result {user "\xyqrszzz" doesn't exist}
test filename-11.11 {Tcl_GlobCmd} -constraints {testsetplatform} -body {
    testsetplatform unix
    glob ~xyqrszzz\\/\\bar
} -returnCodes error -result {user "xyqrszzz" doesn't exist}
test filename-11.12 {Tcl_GlobCmd} -constraints {testsetplatform} -setup {
    testsetplatform unix
    set home $env(HOME)
} -body {
    unset env(HOME)
    glob ~/*
} -returnCodes error -cleanup {
    set env(HOME) $home
} -result {couldn't find HOME environment variable to expand path}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}
test filename-11.13 {Tcl_GlobCmd} {
    file join [lindex [glob ~] 0]
} [file join $env(HOME)]
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} {
    glob ~/globTest
} [list [file join $env(HOME) globTest]]
test filename-11.15 {Tcl_GlobCmd} {
    glob ~\\/globTest
} [list [file join $env(HOME) globTest]]
test filename-11.16 {Tcl_GlobCmd} {
    glob globTest
} {globTest}
set globname "globTest"
set horribleglobname "glob\[\{Test"
set tildeglobname "./~test.txt"








|







|

|









|









|









|









|









|









|
|


|









|
















|

|









|
>
|
|
|

|
|

|






|



|



|






|

|



|

|

















|

|
|

|







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 {~/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
} -cleanup {
    set env(HOME) $temp
} -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 {~}
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 {~}
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 {~/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 {~\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 {~\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 {~\foo}
test filename-10.20 {Tcl_TranslateFileName} -body {
    testtranslatefilename ~blorp/foo
} -constraints {testtranslatefilename testtranslatefilename} \
    -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 {~\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} -body {
    glob
} -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} -body {
    # Should not error out because of ~
    catch {glob -nocomplain * ~xyqrszzz}
} -result 0
test filename-11.6 {Tcl_GlobCmd} -body {
    glob ~xyqrszzz
} -result {}
test filename-11.7 {Tcl_GlobCmd} -body {
    glob -- -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
} -result {}
test filename-11.10 {Tcl_GlobCmd} -constraints {testsetplatform} -body {
    testsetplatform unix
    glob -nocomplain ~\\xyqrszzz/bar
} -result {}
test filename-11.11 {Tcl_GlobCmd} -constraints {testsetplatform} -body {
    testsetplatform unix
    glob ~xyqrszzz\\/\\bar
} -result {}
test filename-11.12 {Tcl_GlobCmd} -constraints {testsetplatform} -setup {
    testsetplatform unix
    set home $env(HOME)
} -body {
    unset env(HOME)
    glob ~/*
} -cleanup {
    set env(HOME) $home
} -result {}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
}
test filename-11.13 {Tcl_GlobCmd} -body {
    file join [lindex [glob ~] 0]
} -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} -body {
    glob ~/globTest
} -result {}
test filename-11.15 {Tcl_GlobCmd} -body {
    glob ~\\/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
} -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 *]
    }
    catch {
	cd [lindex [file volumes] 0]
	set res2 [glob *]
    }
    list $res1 $res2
} -cleanup {
    cd $tmpd
} -match compareWords -result equal
test filename-11.46 {Tcl_GlobCmd} -returnCodes error -body {







|


|







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] end] -tails *]
    }
    catch {
	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
} -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} {
    glob {}
} {.}
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} {
    glob -types d {}
} {.}
test filename-12.1.3 {simple globbing} {unix} {
    glob -types hidden {}
} {.}
test filename-12.1.4 {simple globbing} -constraints {win} -body {
    glob -types hidden {}
} -returnCodes error -result {no files matched glob pattern ""}
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} {
    glob c:/
} {c:/}
test filename-12.3 {simple globbing} {
    glob -nocomplain \{a1,a2\}
} {}
set globPreResult globTest/
set x1 x1.c
set y1 y1.c
test filename-12.4 {simple globbing} {unixOrWin} {
    lsort [glob globTest/x1.c globTest/y1.c globTest/foo]
} "$globPreResult$x1 $globPreResult$y1"
test filename-12.5 {simple globbing} {
    glob globTest\\/x1.c
} "$globPreResult$x1"
test filename-12.6 {simple globbing} {
    glob globTest\\/\\x1.c
} "$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







|

|


|
|

|
|

|


|


|
|

|
|

|



|

|
|

|
|

|







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} -constraints {unixOrWin} -body {
    glob {}
} -result {.}
test filename-12.1.1 {simple globbing} -constraints {unixOrWin} -body {
    glob -types f {}
} -result {}
test filename-12.1.2 {simple globbing} -constraints {unixOrWin} -body {
    glob -types d {}
} -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 {}
} -result {}
test filename-12.1.5 {simple globbing} -constraints {win} -body {
    glob -types hidden c:/
} -result {}
test filename-12.1.6 {simple globbing} -constraints {win} -body {
    glob c:/
} -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} -constraints {unixOrWin} -body {
    lsort [glob globTest/x1.c globTest/y1.c globTest/foo]
} -result "$globPreResult$x1 $globPreResult$y1"
test filename-12.5 {simple globbing} -body {
    glob globTest\\/x1.c
} -result "$globPreResult$x1"
test filename-12.6 {simple globbing} -body {
    glob globTest\\/\\x1.c
} -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
    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*
} -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"}
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"}
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} {







|











|


|







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 [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
} -result {}
test filename-14.22 {asterisks, question marks, and brackets} -body {
    glob goo/* x*z foo?q
} -result {}
test filename-14.23 {slash globbing} {unix} {
    glob /
} /
test filename-14.23.2 {slash globbing} {win} {
    glob /
} [file norm /]
test filename-14.24 {slash globbing} {win} {
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

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}
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}
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
    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
    # 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}}

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
test filename-15.6 {unix specific globbing} -constraints {unix} -setup {
    global env
    set temp $env(HOME)
} -body {
    set env(HOME) $env(HOME)/globTest/odd\\\[\]*?\{\}name
    glob ~
} -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 {
    glob ~
} -match regexp -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]

# The following tests are only valid for Windows systems.
set oldDir [pwd]
if {[testConstraint win]} {
    cd c:/
    file delete -force globTest
    file mkdir globTest







|











|



|



|
<


<
>









|
<
|
<
<
<
|
<
<
<
<
|

|










|







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

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 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 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 ouster and welch users exists
    glob -nocomplain ~ouster ~foo ~welch
} {/home/ouster /home/welch}
test filename-15.4.1 {no complain: errors, sequencing} {
    # ~xxx no longer expanded so errors about unknown users should not occur

    list [catch {glob -nocomplain ~wontexist ~blahxyz ~} res1] $res1 \
	[catch {glob -nocomplain ~ ~blahxyz ~wontexist} res2] $res2

} {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"
# 15.6 removed. It checked if glob ~ returned valid information if

# home directory contained glob chars. Since ~ expansion is no longer



# supported, the test was meaningless




test filename-15.7 {glob tilde} -body {
    glob ~
} -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 {}

# The following tests are only valid for Windows systems.
set oldDir [pwd]
if {[testConstraint win]} {
    cd c:/
    file delete -force globTest
    file mkdir globTest
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
    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 ~
    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 ~
} -result {}
test fileName-20.7 {Bug 2806250} -setup {
    set savewd [pwd]
    cd [temporaryDirectory]
    set d [makeDirectory isolate]
    makeFile {} ./~test $d
} -body {







|










|







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 [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 [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
    makeFile {} ./~test $d
} -body {
    file tail [lindex [glob -nocomplain isolate/*] 0]
} -cleanup {
    removeFile ./~test $d
    removeDirectory isolate
    cd $savewd
} -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 ~]
    makeFile {} fileName-20.10 $s
    set d [makeDirectory isolate]
    set savewd [pwd]
    cd $d
} -body {
   glob -nocomplain -directory ~ -join * fileName-20.10
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile fileName-20.10 $s
    removeDirectory sub ~










































































} -result ~/sub/fileName-20.10


# cleanup
catch {file delete -force C:/globTest}
cd [temporaryDirectory]
file delete -force globTest
cd $oldpwd
catch {removeDirectory tcl[pid]}







|
<
<
<
<
<
<
<
<
<
<
<
<

|





|




|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>







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












test fileName-20.10 {globbing for special chars} -setup {
    set s [makeDirectory sub [file home]]
    makeFile {} fileName-20.10 $s
    set d [makeDirectory isolate]
    set savewd [pwd]
    cd $d
} -body {
    glob -nocomplain -directory [file home] -join * fileName-20.10
} -cleanup {
    cd $savewd
    removeDirectory isolate
    removeFile fileName-20.10 $s
    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
# 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.
#
# 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]
    set ::ddever [package require dde]
    set ::ddelib [lindex [package ifneeded dde $::ddever] 1]
    set ::regver  [package require registry]
    set ::reglib [lindex [package ifneeded registry $::regver] 1]
    testConstraint loaddll 1
}

# Test for commands defined in Tcltest executable
testConstraint testfilesystem  	    [llength [info commands ::testfilesystem]]
testConstraint testsetplatform 	    [llength [info commands ::testsetplatform]]
testConstraint testsimplefilesystem [llength [info commands ::testsimplefilesystem]]


testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

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]







|




















|

|

|
|


|



>
>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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 © 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 tcl::test [info patchlevel]
    set ::ddever [package require dde]
    set ::ddelib [info loaded {} Dde]
    set ::regver  [package require registry]
    set ::reglib [info loaded {} Registry]
    testConstraint loaddll [expr {$::ddelib ne "" && $::reglib ne ""}]
}

# 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 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
		testConstraint unusedDrive 1
		break
	    }
	}

	set dir [pwd]
	try {
	    foreach vol [file volumes] {
		if {![catch {cd $vol}]} {
		    lappend drives $vol
		}

	    }
	    testConstraint moreThanOneDrive [llength $drives]
	} finally {
	    cd $dir
	}
    }
} ::tcl::test::fileSystem}

proc testPathEqual {one two} {







|
|
|
|
>
|
|







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 {
            set drives [lmap vol [file volumes] {
                if {$vol eq [zipfs root] || [catch {cd $vol}]} {
                    continue
                }
                set vol
            }]
	    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
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
} {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







|







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}
} {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
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 {


    file normalize ~noonewiththisname
} -returnCodes error -result {user "noonewiththisname" doesn't exist}
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}
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
	# since this is a Windows test.
	regexp {C:/bar$} $res res
    }
    set res
} {C:/bar}
if {[testConstraint testsetplatform]} {
    testsetplatform $platform







|
>
>

|

|
|
|
>
>
|
>
>
>
>
>
|












|







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
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 - verify no tilde expansion
} -body {
    file normalize ~noonewiththisname
} -result [file join [pwd] ~noonewiththisname]
test filesystem-1.30.1 {normalisation of existing user} -body {
    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
	# 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
} 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 {
    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 {







|







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 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
} 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
    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
    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 {







|
|




|







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} -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
    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
    testfilesystem 1
    set filesystemReport {}
    catch {glob *}
    testfilesystem 0
    return $filesystemReport
} -match glob -result {*{matchindirectory *}*}


test filesystem-5.1 {cache and ~} -constraints testfilesystem -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]"







>
|
>
>







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 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
    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

    cd [file dirname $::ddelib]






    testsimplefilesystem 1
    # This loads dde via a complex copy-to-temp operation
    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

    cd [file dirname $::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.







>
|
>
>
>
>
>
>


|










>
|
>
>
>
>
>
>







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]
    } 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
    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]
    } 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
    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}
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
    # 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}
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]







|











|












|







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 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 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 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
    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}
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]







|







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 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
    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}
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







|







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 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
    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}}
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}}
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}

# ----------------------------------------------------------------------

test filesystem-10.1 {Bug 3414754} {
    string match */ [file join [pwd] foo/]
} 0








|

















|

















|







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 {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 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 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
#!  /usr/bin/env tclsh

# Copyright (c) 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

    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

    package require tcltests

    test filesystemEncoding-1.0 {
	issue bcd100410465
    } -body {
	set dir [tcltests::tempdir]
	set saved [encoding system]
	encoding system iso8859-1


|












|

<
<
<
<
<
<
<
<
<
<
<
<
|
<







1
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 © 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 登鸛鵲樓













    source [file join [file dirname [info script]] tcltests.tcl]


    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
# 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.
#
# 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]} {
	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
	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
	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]} {}
    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} {
	set a [concat $a $i]
    }
    set a
} {1 2 3}

# cleanup
::tcltest::cleanupTests
return








|
|














|






|
|






|
|
















|




|








1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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 © 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} {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} {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} {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} {incr i} {}
    set a
} xyz
test for-old-1.9 {for tests} {
    set a {}
    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
# 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.
#
# 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::*






|







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 © 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
    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
	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"
    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
    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
	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







|
|






|










|










|
|
|







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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} {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} {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} {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} {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
    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
} {}

# 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]} {
	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]} {
	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"]
        }
    }
    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
	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
    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
} {}

# 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} {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} {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"]
        }
    }
    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} {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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
            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
	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>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







|
|
|
|















|







242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
            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} {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>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
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
        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,} \







|







333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
        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,} \
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 {
	    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







|







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} {
	    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
		append result $line $NL
		if {[string length $F1] == 0} {
		    set F1 -1
		}
		continue
	    }
	}
	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} {
		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]
		} else {
		    set c [string length $line]
		}
	    }
	    set newline [string trimright [string range $line 0 $c]]
	    if {! $continuation} {
		append result $newline $NL







|




|










|







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 cutoff 50
	set continuation 0

	while {[string length $line] > $limit} {
	    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}]
		} 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
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
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







|







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

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
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
}

# 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
        }
    } j
    set j
} {}

# Test for incorrect "double evaluation" semantics







|







581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
}

# 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
        }
    } j
    set j
} {}

# Test for incorrect "double evaluation" semantics
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
	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"
    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
    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
	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







|
|







|











|















|
|
|







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} {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} {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} {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} {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

Changes to tests/foreach.test.

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.
#
# 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::*






|
|







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 © 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::*
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    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
} 13.0

# Check "continue".

test foreach-5.1 {continue tests} {catch continue} 4







|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    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
} 13.0

# Check "continue".

test foreach-5.1 {continue tests} {catch continue} 4

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
# 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.
#
# 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.
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}]



testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

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 {






|
|














>
>
>
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 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 © 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.
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 {![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 {
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
    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}
test format-1.14 {integer formatting} {
    format "%#05d %#020d %#020d %#020d %#020d" 0 6 34 16923 -12 -1
} {00000 00000000000000000006 00000000000000000034 00000000000000016923 -0000000000000000012}
test format-1.15 {integer formatting} {
    format "%-#05d %-#020d %-#020d %-#020d %-#020d" 0 6 34 16923 -12 -1
} {00000 00000000000000000006 00000000000000000034 00000000000000016923 -0000000000000000012}


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"
test format-2.6 {string formatting, international chars} {
    format "%10s" abc\ufeffdef
} "   abc\ufeffdef"
test format-2.7 {string formatting, international chars} {
    format "%.5s" abc\ufeffdef
} "abc\ufeffd"
test format-2.8 {string formatting, international chars} {
    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} {







|


|


|















|
|

|
|

|
|

|
|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
    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 0d6 0d34 0d16923 -0d12}
test format-1.14 {integer formatting} {
    format "%#05d %#020d %#020d %#020d %#020d" 0 6 34 16923 -12 -1
} {00000 0d000000000000000006 0d000000000000000034 0d000000000000016923 -0d00000000000000012}
test format-1.15 {integer formatting} {
    format "%-#05d %-#020d %-#020d %-#020d %-#020d" 0 6 34 16923 -12 -1
} {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\x00def
} "   abc\x00def"
test format-2.6 {string formatting, international chars} {
    format "%10s" abc\uFEFFdef
} "   abc\uFEFFdef"
test format-2.7 {string formatting, international chars} {
    format "%.5s" abc\uFEFFdef
} "abc\uFEFFd"
test format-2.8 {string formatting, international chars} {
    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
} {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-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   |"

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}







>
>
>
>
>
>





|
|







139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
} {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
} "|¢||ɚ|Ã|(     |     \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}
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 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]
} -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]
} -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]
} -result {0x80000000 0x80000000}
test format-8.27 {Undocumented formats} -constraints pointerIs64bit -body {
    format "%p %#llx" [expr 2**33] [expr 2**33]
} -result {0x200000000 0x200000000}




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} {







|


|






|


|

>
>
>







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
    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}]
} -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}]
} -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}]
} -result {0x80000000 0x80000000}
test format-8.27 {Undocumented 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
} {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-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]
    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]
    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]
    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]
    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]
    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} {







>
>
>
>
>
>













|










|








|








|








|







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
} {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}]
    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}]
    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}]
    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}]
    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}]
    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

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
    } $b
    append b "x"
}

test format-17.1 {testing %d with wide} {longIs32bit wideIs64bit} {
    format %d 7810179016327718216







|







554
555
556
557
558
559
560
561
562
563
564
565
566
567
568

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
    } $b
    append b "x"
}

test format-17.1 {testing %d with wide} {longIs32bit wideIs64bit} {
    format %d 7810179016327718216
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
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 {
    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.
    # 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}







|




|







625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
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 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 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
# 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.
#
# 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]]



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} {
    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} {
    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} {
    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} {
    list [catch {testgetint 4294967294} msg] $msg
} {0 -2}
test get-1.13 {Tcl_GetInt procedure} {testgetint longIs32bit} {
    list [catch {testgetint +4294967294} msg] $msg
} {0 -2}
test get-1.14 {Tcl_GetInt procedure} {testgetint longIs32bit} {
    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} {






|
|










|
>
>



<




















|








|


|


|


|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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 © 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]]

source [file join [file dirname [info script]] tcltests.tcl]

testConstraint testgetint [llength [info commands testgetint]]
testConstraint testdoubleobj [llength [info commands testdoubleobj]]

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 {
    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 {
    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 {
    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 {
    list [catch {testgetint 4294967294} msg] $msg
} {0 -2}
test get-1.13 {Tcl_GetInt procedure} testgetint {
    list [catch {testgetint +4294967294} msg] $msg
} {0 -2}
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} {
99
100
101
102
103
104
105

106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122
123
124
125
# 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"} {
	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}

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 } {
	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"}}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>

|



|
>

|



|








100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# 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" "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 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 " 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 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
# 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.
#
# 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::*






|
|
|







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 © 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

# "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]} \
	{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 {
    catch {history event 123 456} msg
    set msg
} {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 {
    catch {history redo -3 -4} msg
    set msg
} {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







|













|


|














|


|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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}]} \
	{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} -constraints history -body {
    catch {history event 123 456} msg
    set msg
} -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} -constraints history -body {
    catch {history redo -3 -4} msg
    set msg
} -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
}
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 {
    catch {history add "set a 666" e f} msg
    set msg
} {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 {
    catch {history change Foo 4 10} msg
    set msg
} {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 {







|


|















|


|







98
99
100
101
102
103
104
105
106
107
108
109
110
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} -constraints history -body {
    catch {history add "set a 666" e f} msg
    set msg
} -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} -constraints history -body {
    catch {history change Foo 4 10} msg
    set msg
} -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
    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]]
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]]
test history-5.3 {info option} history {catch {history i 2 3}} 1
test history-5.4 {info option} history {
    catch {history i 2 3} msg
    set msg
} {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]]

# "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.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 {
    catch {history keep 4 6} msg
    set msg
} {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







|



|

|


|





|









|
>
>















|


|







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
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}]]
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}]]
test history-5.3 {info option} history {catch {history i 2 3}} 1
test history-5.4 {info option} -constraints history -body {
    catch {history i 2 3} msg
    set msg
} -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}]]

# "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.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} -constraints history -body {
    catch {history keep 4 6} msg
    set msg
} -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

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.3 {nextid option} history {catch {history nextid garbage}} 1
test history-7.4 {nextid option} history {
    catch {history nextid garbage} msg
    set msg
} {wrong # args: should be "history nextid"}

# "history clear"

if {[testConstraint history]} {
    set num [history n]
    history add "Testing"
    history add "Testing2"







|

|


|







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.3 {nextid option} history {catch {history nextid garbage}} 1
test history-7.4 {nextid option} -constraints history -body {
    catch {history nextid garbage} msg
    set msg
} -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
	    # 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 baseline [refcount $obj]
	lappend result [refcount $obj]
	history add [list list $obj]
	lappend result [refcount $obj]
	history clear
	lappend result [refcount $obj]
    }







|







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 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
	    # 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 baseline [refcount $obj]
	lappend result [refcount $obj]
	history add [list list $obj]
	lappend result [refcount $obj]
	rename history {}
	lappend result [refcount $obj]
    }







|







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 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
# 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.
#
# 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]} {
	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
    }
}



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
} else {
    set HOST [info hostname]
}

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]

    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
    }

}
































test http-1.1 {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} {
    http::config -proxyfilter
} http::ProxyRequired
test http-1.3 {http::config} {
    catch {http::config -junk}
} 1
test http-1.4 {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 {
    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 {
    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} {
    catch {http::reset http#1}
} 0






















test http-3.1 {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 {
    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 token [http::geturl $url]
    http::data $token
} -cleanup {
    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 {
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    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 {
    http::config -proxyfilter selfproxy
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    http::config -proxyfilter http::ProxyRequired
    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 {
    http::config -proxyfilter bogus
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    http::config -proxyfilter http::ProxyRequired
    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 {
    set token [http::geturl $url -headers {Pragma no-cache}]
    http::data $token
} -cleanup {
    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 {
    set token [http::geturl $url -query Name=Value&Foo=Bar -timeout 3000]
    http::data $token
} -cleanup {
    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 {
    set token [http::geturl $url -validate 1]
    http::code $token
} -cleanup {
    http::cleanup $token
} -result "HTTP/1.0 200 OK"
test http-3.10 {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} {
	global postProgress
	lappend postProgress $y
    }
    set postProgress {}
    set t [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]
} -cleanup {
    http::cleanup $t
} -result {ok 122879 {16384 32768 49152 65536 81920 98304 114688 122879} {Got 122879 bytes}}
test http-3.11 {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} {
	global postResult
	lappend postResult [http::data $token]
    }
    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]]
    # Now do async
    http::cleanup $t
    close $fp
    set fp [open $file]
    set t [http::geturl $posturl -querychannel $fp -command asyncCB]
    set postResult [list PostStart]
    http::wait $t
    close $fp
    lappend testRes [http::status $t] $postResult
} -cleanup {
    removeFile outdata
    http::cleanup $t
} -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 {
    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} {
	global postResult
	lappend postResult [http::data $token]
    }
    proc postProgress {token 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 \
		-queryprogress postProgress]
	http::wait $t
	upvar #0 $t state
    } err]} {
	puts $::errorInfo
	error $err
    }
    list [http::status $t] [http::code $t]
} -cleanup {
    removeFile outdata
    http::cleanup $t
} -result {ok {HTTP/1.0 200 Data follows}}
test http-3.13 {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 {
    set token [http::geturl $fullurl -validate 1]
    http::code $token
} -cleanup {
    http::cleanup $token
} -result "HTTP/1.0 200 OK"
test http-3.15 {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 {
    http::geturl http:relative/url
} -returnCodes error -result {Unsupported URL: http:relative/url}
test http-3.17 {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 {
    http::geturl http://somewhere:123456789/
} -returnCodes error -result {Invalid port number: 123456789}
test http-3.19 {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 {
    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 {
    http::geturl http://somewhere/{path}
} -returnCodes error -result {Illegal characters in URL path}
test http-3.22 {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 {
    http::geturl http://somewhere/path?{query}?
} -returnCodes error -result {Illegal characters in URL path}
test http-3.24 {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 {
    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
    unset -nocomplain m token
} -result {Content-Length Content-Type Date}
test http-3.26 {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
    unset -nocomplain m token
} -result {Content-Length Content-Type Date X-Check}
test http-3.27 {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
} -match regexp -result {(?n)Host .*
User-Agent .*
Connection close
Content-Type {text/plain;charset=utf-8}
Accept \*/\*
Accept-Encoding .*

Content-Length 5}
test http-3.28 {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
} -match regexp -result {(?n)Host .*
User-Agent .*
Connection close
Content-Type {text/plain;charset=utf-8}
Accept \*/\*
Accept-Encoding .*

Content-Length 5}
test http-3.29 {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
} -cleanup {
    catch { http::cleanup $token }
} -result 0
test http-3.30 {http::geturl query without path} -body {
    set token [http::geturl $authorityurl?var=val]
    http::ncode $token
} -cleanup {
    catch { http::cleanup $token }
} -result 200
test http-3.31 {http::geturl fragment without path} -body {
    set token [http::geturl "$authorityurl#fragment42"]
    http::ncode $token
} -cleanup {
    catch { http::cleanup $token }
} -result 200
# Bug c11a51c482
test http-3.32 {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
} -match regexp -result {(?n)Host .*
User-Agent .*
Connection close
Accept text/plain,application/tcl-test-value
Accept-Encoding .*

Content-Type application/x-www-form-urlencoded
Content-Length 5}
# Bug 838e99a76d
test http-3.33 {http::geturl application/xml is text} -body {
    set token [http::geturl "$xmlurl"]
    scan [http::data $token] "<%\[^>]>%c<%\[^>]>"
} -cleanup {
    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-4.1 {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))}
} -cleanup {
    http::cleanup $token
} -result 1
test http-4.2 {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)]
} -cleanup {
    http::cleanup $token
} -result 0
test http-4.3 {http::Event} -body {
    set token [http::geturl $url]
    http::code $token
} -cleanup {
    http::cleanup $token
} -result {HTTP/1.0 200 Data follows}
test http-4.4 {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
} -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 {
    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
} -result 1
test http-4.6 {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
} -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 {
    set token [http::geturl $url -blocksize 50 -progress myProgress]
    return $progress
} {111 111}
test http-4.7 {http::Event} -body {
    set token [http::geturl $url -keepalive 0 -progress myProgress]
    return $progress
} -cleanup {
    http::cleanup $token
} -result {111 111}
test http-4.8 {http::Event} -body {
    set token [http::geturl $url]
    http::status $token
} -cleanup {
    http::cleanup $token
} -result {ok}
test http-4.9 {http::Event} -body {
    set token [http::geturl $url -progress myProgress]
    http::code $token
} -cleanup {
    http::cleanup $token
} -result {HTTP/1.0 200 Data follows}
test http-4.10 {http::Event} -body {
    set token [http::geturl $url -progress myProgress]
    http::size $token
} -cleanup {
    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 {
    set token [http::geturl $url -timeout 1 -keepalive 0 -command \#]
    http::reset $token
    http::status $token
} -cleanup {
    http::cleanup $token
} -result {reset}

#	Longer timeout with reset.
test http-4.12 {http::Event} -body {
    set token [http::geturl $url/?timeout=10 -keepalive 0 -command \#]
    http::reset $token
    http::status $token
} -cleanup {
    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 {
    set token [http::geturl $url?timeout=30 -keepalive 0 -timeout 10 -command \#]
    http::wait $token
    http::status $token
} -cleanup {
    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 {
    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}

# 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 \#]
    http::wait $token


    http::status $token
    # 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 {
    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} {
    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} {
    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
} {name1=~bwelch&name2=%C2%A1%C2%A2%C2%A2}
test http-5.5 {http::formatQuery} {
    set enc [http::config -urlencoding]
    http::config -urlencoding iso8859-1
    set res [http::formatQuery name1 ~bwelch name2 \xa1\xa2\xa2]
    http::config -urlencoding $enc
    set res
} {name1=~bwelch&name2=%A1%A2%A2}

test http-6.1 {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
} -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} {
    http::mapReply "abc\$\[\]\"\\()\}\{"
} {abc%24%5B%5D%22%5C%28%29%7D%7B}
test http-7.2 {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"
} {%E2%88%88}
test http-7.3 {http::formatQuery} -setup {
    set enc [http::config -urlencoding]
} -returnCodes error -body {
    # this would be reverting to http <=2.4 behavior
    http::config -urlencoding ""
    http::mapReply "\u2208"
} -cleanup {
    http::config -urlencoding $enc
} -result "can't read \"formMap(\u2208)\": no such element in array"
test http-7.4 {http::formatQuery} -setup {
    set enc [http::config -urlencoding]


} -body {
    # this would be reverting to http <=2.4 behavior w/o errors
    # (unknown chars become '?')

    http::config -urlencoding "iso8859-1"
    http::mapReply "\u2208"
} -cleanup {
    http::config -urlencoding $enc
} -result {%3F}

package require tcl::idna 1.0

test http-idna-1.1 {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 {
    ::tcl::idna ?
} -result {unknown or ambiguous subcommand "?": must be decode, encode, puny, or version}
test http-idna-1.3 {IDNA package: basics} -body {
    ::tcl::idna version
} -result 1.0.1
test http-idna-1.4 {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 {
    ::tcl::idna puny
} -result {wrong # args: should be "::tcl::idna puny subcommand ?arg ...?"}
test http-idna-1.6 {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 {
    ::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 {
    ::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 {
    ::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 {
    ::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 {
    ::tcl::idna decode
} -result {wrong # args: should be "::tcl::idna decode hostname"}
test http-idna-1.12 {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} {
    ::tcl::idna puny encode abc
} abc-
test http-idna-2.2 {puny encode: functional test} {
    ::tcl::idna puny encode a\u20acb\u20acc
} abc-k50ab
test http-idna-2.3 {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
} ABC-k50ab
test http-idna-2.5 {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
} abc-k50ab
test http-idna-2.7 {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
} ABC-k50ab
test http-idna-2.9 {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
} abc-k50ab
test http-idna-2.11 {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
} ABC-k50ab
test http-idna-2.13 {puny encode: edge cases} {
    ::tcl::idna puny encode ""
} ""
test http-idna-2.14-A {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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::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} {
    ::tcl::idna puny encode {-> $1.00 <-}
} {-> $1.00 <--}

test http-idna-3.1 {puny decode: functional test} {
    ::tcl::idna puny decode abc-
} abc
test http-idna-3.2 {puny decode: functional test} {
    ::tcl::idna puny decode abc-k50ab
} a\u20acb\u20acc
test http-idna-3.3 {puny decode: functional test} {
    ::tcl::idna puny decode ABC-
} ABC
test http-idna-3.4 {puny decode: functional test} {
    ::tcl::idna puny decode ABC-k50ab
} A\u20ACB\u20ACC
test http-idna-3.5 {puny decode: functional test} {
    ::tcl::idna puny decode ABC-K50AB
} A\u20ACB\u20ACC
test http-idna-3.6 {puny decode: functional test} {
    ::tcl::idna puny decode abc-K50AB
} a\u20ACb\u20ACc
test http-idna-3.7 {puny decode: functional test} {
    ::tcl::idna puny decode ABC- 0
} abc
test http-idna-3.8 {puny decode: functional test} {
    ::tcl::idna puny decode ABC-K50AB 0
} a\u20ACb\u20ACc
test http-idna-3.9 {puny decode: functional test} {
    ::tcl::idna puny decode ABC- 1
} ABC
test http-idna-3.10 {puny decode: functional test} {
    ::tcl::idna puny decode ABC-K50AB 1
} A\u20ACB\u20ACC
test http-idna-3.11 {puny decode: functional test} {
    ::tcl::idna puny decode abc- 0
} abc
test http-idna-3.12 {puny decode: functional test} {
    ::tcl::idna puny decode abc-k50ab 0
} a\u20ACb\u20ACc
test http-idna-3.13 {puny decode: functional test} {
    ::tcl::idna puny decode abc- 1
} ABC
test http-idna-3.14 {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} {
    # 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 {
    ::tcl::idna puny decode abc!
} -result {bad decode character "!"}
test http-idna-3.17 {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} {
    ::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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    ::tcl::idna puny decode {-> $1.00 <--}
} {-> $1.00 <-}
rename hexify ""

test http-idna-4.1 {IDNA encoding} {
    ::tcl::idna encode abc.def
} abc.def
test http-idna-4.2 {IDNA encoding} {
    ::tcl::idna encode a\u20acb\u20acc.def
} xn--abc-k50ab.def
test http-idna-4.3 {IDNA encoding} {
    ::tcl::idna encode def.a\u20acb\u20acc
} def.xn--abc-k50ab
test http-idna-4.4 {IDNA encoding} {
    ::tcl::idna encode ABC.DEF
} ABC.DEF
test http-idna-4.5 {IDNA encoding} {
    ::tcl::idna encode A\u20acB\u20acC.def
} xn--ABC-k50ab.def
test http-idna-4.6 {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 {
    ::tcl::idna encode abc.$.def
} -result {bad character "$" in DNS name}
test http-idna-4.7.1 {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} {
    ::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 {
    ::tcl::idna encode $overlong
} -returnCodes error -result "hostname part too long"
test http-idna-4.9.1 {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
} xn--pass-epa.example.com

test http-idna-5.1 {IDNA decoding} {
    ::tcl::idna decode abc.def
} abc.def
test http-idna-5.2 {IDNA decoding} {
    # Invalid entry that's just a wrapper
    ::tcl::idna decode xn--abc-.def
} abc.def
test http-idna-5.3 {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} {
    # 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 {
    ::tcl::idna decode xn--$$$.example.com
} -result {bad decode character "$"}
test http-idna-5.5.1 {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 {
    ::tcl::idna decode xn--a-zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz.def
} -result {exceeded input data}
test http-idna-5.6.1 {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
} else {
    close $listen
}

if {[info exists removeHttpd]} {
    removeFile $httpdFile
}

rename bgerror {}


::tcltest::cleanupTests


# Local variables:
# mode: tcl
# End:






|
|
|









|
|
<
<
<
<
<
<
<
<
<
<
|
<
>
>








|
|
>
|
<
<
<
<
|
















>

















>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


|
|


|


|







|
|

|
|









|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|

|
>
|


>

|
|



|




>









>
|



|








|





|




|





|




|



|




|



|









|



|

|










|




|

|
|

|

|












|

|


|
|
|

|


|

|

|


|






|












|

|

|







|

|
|




|


|

|







|



|

|


|


|


|


|


|


|


|


|


|


|






|

|
|






|

|
|




|


<



>

|




|


<



>

|











|

|



|

|



|


|




|


<


>



|



|

|
|
>
>
>
|

|



|

|

|



|

|

|



|

|











|




|










|

|












|








|



|



|

|



|

|



|

|



|

>



|




|

>

|




|

>


|




|

>


|








|
>

|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|

>
>
|



|
>
|














|



|


|
|

|


|




|







|





|


|


|

|


|

|


|
|

>
>


|
>

|


|



|


|


|


|


|


|


|


|


|


|


|


|



|


|
|

|


|
|

|


|
|

|


|
|

|


|
|

|


|
|

|


|





|




|




|






|






|







|





|






|







|








|







|




|






|






|




|





|




|




|



|


|

|
|


|

|
|

|
|

|
|


|

|
|


|

|
|


|

|
|


|

|
|



|


|



|




|





|


|


|






|






|








|





|







|







|









|








|


|






|






|


|





|


|


|




|


|
|

|
|

|


|
|

|



|


|



|







|


|




|
|


|


|



|



|



|


|



|


|









|
|









>
>
|
>




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20










21

22
23
24
25
26
27
28
29
30
31
32
33
34
35




36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 © 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::*
}

package require http 2.10
#http::register http 80 ::socket












# 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
}

# 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




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 {}
}

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 -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.$ThreadLevel {http::config} {
    catch {http::config -junk}
} 1
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
} [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, -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.$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.$ThreadLevel {http::geturl} -returnCodes error -body {
    http::geturl -bogus flag
} -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.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    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.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    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.$ThreadLevel {http::geturl} -body {
    http::config -proxyfilter selfproxy
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    http::config -proxyfilter http::ProxyRequired
    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.$ThreadLevel {http::geturl} -body {
    http::config -proxyfilter bogus
    set token [http::geturl $url]
    http::data $token
} -cleanup {
    http::config -proxyfilter http::ProxyRequired
    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.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url -headers {Pragma no-cache}]
    http::data $token
} -cleanup {
    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.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url -query Name=Value&Foo=Bar -timeout 3000]
    http::data $token
} -cleanup {
    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.$ThreadLevel {http::geturl} -body {
    set token [http::geturl $url -validate 1]
    http::code $token
} -cleanup {
    catch {http::cleanup $token}
} -result "HTTP/1.0 200 OK"
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 {tok x y} {
	global postProgress
	lappend postProgress $y
    }
    set postProgress {}
    set token [http::geturl $posturl -keepalive 0 -query $query \
	    -queryprogress postProgress -queryblocksize 16384]
    http::wait $token
    list [http::status $token] [string length $query] $postProgress [http::data $token]
} -cleanup {
    catch {http::cleanup $token}
} -result {ok 122879 {16384 32768 49152 65536 81920 98304 114688 122879} {Got 122879 bytes}}
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 {tok} {
	global postResult
	lappend postResult [http::data $tok]
    }
    set postResult [list ]
    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 $token
    close $fp
    set fp [open $file]
    set token [http::geturl $posturl -querychannel $fp -command asyncCB]
    set postResult [list PostStart]
    http::wait $token
    close $fp
    lappend testRes [http::status $token] $postResult
} -cleanup {
    removeFile outdata
    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.$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 {tok} {
	global postResult
	lappend postResult [http::data $tok]
    }
    proc postProgress {tok x y} {
	global postProgress
	lappend postProgress $y
    }
    set postProgress {}
    # Now do async
    set postResult [list PostStart]
    if {[catch {
	set token [http::geturl $badposturl -querychannel $fp -command asyncCB \
		-queryprogress postProgress]
	http::wait $token
	upvar #0 $token state
    } err]} {
	puts $::errorInfo
	error $err
    }
    list [http::status $token] [http::code $token]
} -cleanup {
    removeFile outdata
    catch {http::cleanup $token}
} -result {ok {HTTP/1.0 200 Data follows}}
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.$ThreadLevel "http::geturl $fullurl" -body {
    set token [http::geturl $fullurl -validate 1]
    http::code $token
} -cleanup {
    catch {http::cleanup $token}
} -result "HTTP/1.0 200 OK"
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.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http:relative/url
} -returnCodes error -result {Unsupported URL: http:relative/url}
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.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://somewhere:123456789/
} -returnCodes error -result {Invalid port number: 123456789}
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.$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.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://somewhere/{path}
} -returnCodes error -result {Illegal characters in URL path}
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.$ThreadLevel {http::geturl parse failures} -body {
    http::geturl http://somewhere/path?{query}?
} -returnCodes error -result {Illegal characters in URL path}
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.$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 {
    catch {http::cleanup $token}
    unset -nocomplain m token
} -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 {
    catch {http::cleanup $token}
    unset -nocomplain m token
} -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 {
    catch {http::cleanup $token}
} -match regexp -result {(?n)Host .*
User-Agent .*

Content-Type {text/plain;charset=utf-8}
Accept \*/\*
Accept-Encoding .*
Connection close
Content-Length 5}
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 {
    catch {http::cleanup $token}
} -match regexp -result {(?n)Host .*
User-Agent .*

Content-Type {text/plain;charset=utf-8}
Accept \*/\*
Accept-Encoding .*
Connection close
Content-Length 5}
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
} -cleanup {
    catch {http::cleanup $token}
} -result 0
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}
} -result 200
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}
} -result 200
# Bug c11a51c482
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 {
    catch {http::cleanup $token}
} -match regexp -result {(?n)Host .*
User-Agent .*

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.$ThreadLevel {http::geturl application/xml is text} -body {
    set token [http::geturl "$xmlurl"]
    scan [http::data $token] "<%\[^>]>%c<%\[^>]>"
} -cleanup {
    catch {http::cleanup $token}
} -result {test 4660 /test}
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.$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))}
} -cleanup {
    catch {http::cleanup $token}
} -result 1
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)]
} -cleanup {
    catch {http::cleanup $token}
} -result 0
test http-4.3.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url]
    http::code $token
} -cleanup {
    catch {http::cleanup $token}
} -result {HTTP/1.0 200 Data follows}
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
    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.$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
    catch {http::cleanup $token}
} -result 1
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
    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.$ThreadLevel {http::Event} knownBug {
    set token [http::geturl $url -blocksize 50 -progress myProgress]
    return $progress
} {111 111}
test http-4.7.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url -keepalive 0 -progress myProgress]
    return $progress
} -cleanup {
    catch {http::cleanup $token}
} -result {111 111}
test http-4.8.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url]
    http::status $token
} -cleanup {
    catch {http::cleanup $token}
} -result {ok}
test http-4.9.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url -progress myProgress]
    http::code $token
} -cleanup {
    catch {http::cleanup $token}
} -result {HTTP/1.0 200 Data follows}
test http-4.10.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url -progress myProgress]
    http::size $token
} -cleanup {
    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.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url -timeout 1 -keepalive 0 -command \#]
    http::reset $token
    http::status $token
} -cleanup {
    catch {http::cleanup $token}
} -result {reset}

#	Longer timeout with reset.
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 {
    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.$ThreadLevel {http::Event} -body {
    set token [http::geturl $url?timeout=30 -keepalive 0 -timeout 10 -command \#]
    http::wait $token
    http::status $token
} -cleanup {
    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.$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}

# Bogus host
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"
    set result "[http::status $token] -- [lindex [http::error $token] 0]"
    # error codes vary among platforms.
} -cleanup {
    catch {http::cleanup $token}
} -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.$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.$ThreadLevel {http::formatQuery} {
    http::formatQuery lines "line1\nline2\nline3"
} {lines=line1%0D%0Aline2%0D%0Aline3}
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.$ThreadLevel {http::formatQuery} {
    set enc [http::config -urlencoding]
    http::config -urlencoding iso8859-1
    set res [http::formatQuery name1 ~bwelch name2 ¡¢¢]
    http::config -urlencoding $enc
    set res
} {name1=~bwelch&name2=%A1%A2%A2}

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 {}
    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.$ThreadLevel {http::mapReply} {
    http::mapReply "abc\$\[\]\"\\()\}\{"
} {abc%24%5B%5D%22%5C%28%29%7D%7B}
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 ""
} {%E2%88%88}
test http-7.3.$ThreadLevel {http::formatQuery} -setup {
    set enc [http::config -urlencoding]
} -returnCodes error -body {
    # -urlencoding "" no longer supported. Use "iso8859-1".
    http::config -urlencoding ""
    http::mapReply ""
} -cleanup {
    http::config -urlencoding $enc
} -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
    # with Tcl 8.x (unknown chars become '?'), generating a
    # proper exception with Tcl 9.0
    http::config -urlencoding "iso8859-1"
    http::mapReply ""
} -cleanup {
    http::config -urlencoding $enc
} -errorCode {TCL ENCODING ILLEGALSEQUENCE 0} -result {unexpected character at index 0: 'U+002208'}

package require tcl::idna 1.0

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.$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.$ThreadLevel {IDNA package: basics} -body {
    ::tcl::idna version
} -result 1.0.1
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.$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.$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.$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.$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.$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.$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.$ThreadLevel {IDNA package: basics} -returnCodes error -body {
    ::tcl::idna decode
} -result {wrong # args: should be "::tcl::idna decode hostname"}
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.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode abc
} abc-
test http-idna-2.2.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode abc
} abc-k50ab
test http-idna-2.3.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode ABC
} ABC-
test http-idna-2.4.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode ABC
} ABC-k50ab
test http-idna-2.5.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode ABC 0
} abc-
test http-idna-2.6.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode ABC 0
} abc-k50ab
test http-idna-2.7.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode ABC 1
} ABC-
test http-idna-2.8.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode ABC 1
} ABC-k50ab
test http-idna-2.9.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode abc 0
} abc-
test http-idna-2.10.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode abc 0
} abc-k50ab
test http-idna-2.11.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode abc 1
} ABC-
test http-idna-2.12.$ThreadLevel {puny encode: functional test} {
    ::tcl::idna puny encode abc 1
} ABC-k50ab
test http-idna-2.13.$ThreadLevel {puny encode: edge cases} {
    ::tcl::idna puny encode ""
} ""
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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$ThreadLevel {puny encode: examples from RFC 3492} {
    ::tcl::idna puny encode {-> $1.00 <-}
} {-> $1.00 <--}

test http-idna-3.1.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-
} abc
test http-idna-3.2.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-k50ab
} abc
test http-idna-3.3.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-
} ABC
test http-idna-3.4.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-k50ab
} ABC
test http-idna-3.5.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-K50AB
} ABC
test http-idna-3.6.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-K50AB
} abc
test http-idna-3.7.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC- 0
} abc
test http-idna-3.8.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-K50AB 0
} abc
test http-idna-3.9.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC- 1
} ABC
test http-idna-3.10.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode ABC-K50AB 1
} ABC
test http-idna-3.11.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc- 0
} abc
test http-idna-3.12.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-k50ab 0
} abc
test http-idna-3.13.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc- 1
} ABC
test http-idna-3.14.$ThreadLevel {puny decode: functional test} {
    ::tcl::idna puny decode abc-k50ab 1
} ABC
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.$ThreadLevel {puny decode: edge cases and errors} -returnCodes error -body {
    ::tcl::idna puny decode abc!
} -result {bad decode character "!"}
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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$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.$ThreadLevel {puny decode: examples from RFC 3492} {
    ::tcl::idna puny decode {-> $1.00 <--}
} {-> $1.00 <-}
rename hexify ""

test http-idna-4.1.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode abc.def
} abc.def
test http-idna-4.2.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode abc.def
} xn--abc-k50ab.def
test http-idna-4.3.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode def.abc
} def.xn--abc-k50ab
test http-idna-4.4.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode ABC.DEF
} ABC.DEF
test http-idna-4.5.$ThreadLevel {IDNA encoding} {
    ::tcl::idna encode ABC.def
} xn--ABC-k50ab.def
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.$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.$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.$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.$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.$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.$ThreadLevel {IDNA encoding: edge cases} {
    ::tcl::idna encode passé.example.com
} xn--pass-epa.example.com

test http-idna-5.1.$ThreadLevel {IDNA decoding} {
    ::tcl::idna decode abc.def
} abc.def
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.$ThreadLevel {IDNA decoding} {
    # Invalid entry that's just a wrapper
    ::tcl::idna decode xn--abc-.xn--def-
} abc.def
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.$ThreadLevel {IDNA decoding: error cases} -returnCodes error -body {
    ::tcl::idna decode xn--$$$.example.com
} -result {bad decode character "$"}
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.$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.$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 {[llength $threadStack]} {
    eval [lpop threadStack]
} else {
    close $listen
}

if {[info exists removeHttpd]} {
    removeFile $httpdFile
}

rename bgerror {}

if {[testConstraint ThreadLevelSummary]} {
    ::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
# http11.test --                                                -*- tcl-*-
#
#	Test HTTP/1.1 features.
#
# Copyright (C) 2009 Pat Thoyts <[email protected]>
#
# 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


# start the server
variable httpd_output
proc create_httpd {} {
    proc httpd_read {chan} {
        variable httpd_output
        if {[gets $chan line] >= 0} {




|









|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# http11.test --                                                -*- tcl-*-
#
#	Test HTTP/1.1 features.
#
# Copyright © 2009 Pat Thoyts <[email protected]>
#
# 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
#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} {
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
        vwait httpd_output
        close $httpd
    }
    unset -nocomplain httpd_output httpd
}

proc meta {tok {key ""}} {
    set meta [http::meta $tok]
    if {$key ne ""} {
        if {[dict exists $meta $key]} {
            return [dict get $meta $key]
        } else {
            return ""
        }
    }
    return $meta
}

proc state {tok {key ""}} {
    upvar 1 $tok state
    if {$key ne ""} {
        if {[array names state -exact $key] ne {}} {
            return $state($key)







<
|
<
|
|
|
|
<
<







48
49
50
51
52
53
54

55

56
57
58
59


60
61
62
63
64
65
66
        vwait httpd_output
        close $httpd
    }
    unset -nocomplain httpd_output httpd
}

proc meta {tok {key ""}} {

    if {$key eq ""} {

        return [http::meta $tok]
    } else {
        return [http::metaValue $tok $key]
    }


}

proc state {tok {key ""}} {
    upvar 1 $tok state
    if {$key ne ""} {
        if {[array names state -exact $key] ne {}} {
            return $state($key)
83
84
85
86
87
88
89
90

































91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
116
117
118
119
120
121
122













123
124
125
126
127
128
129
130


131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226













227
228
229
230
231
232
233
234


235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
    if {$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


































# -------------------------------------------------------------------------

test http11-1.0 "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
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close}

test http11-1.1 "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}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]

} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok gzip {}}

test http11-1.2 "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}]
    http::wait $tok













    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok deflate {}}

test http11-1.3 "normal,compressed,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 compress}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok compress {}}

test http11-1.4 "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}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} {}}

test http11-1.5 "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}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding]
} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {}}

test http11-1.6 "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]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok connection] [meta $tok transfer-encoding]

} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close chunked}

test http11-1.7 "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]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok connection] [meta $tok transfer-encoding]
} -cleanup {
    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 {
    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html?close=1 \
                 -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]
} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close {}}

test http11-1.9 "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}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok gzip chunked}

test http11-1.10 "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}]
    http::wait $tok













    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok deflate chunked}

test http11-1.11 "normal,compress,chunked" -setup {


    variable httpd [create_httpd]
} -body {
    set tok [http::geturl http://localhost:$httpd_port/testdoc.html \
                 -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]
} -cleanup {
    http::cleanup $tok
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok compress chunked}

test http11-1.12 "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}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding]
} -cleanup {
    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 {
    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]
    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]]
    set toj [http::geturl http://localhost:$httpd_port/testdoc.html?transfer= \
                 -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]]
    concat $res1 -- $res2
} -cleanup {
    http::cleanup $tok
    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 {
    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]
    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]
} -cleanup {
    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 {
    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}]
    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 {
    http::cleanup $tok
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close gzip chunked}

test http11-2.2 "-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}]
    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 {
    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 {


    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}]
    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 {
    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 {
    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}]
    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 {
    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 {
    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]]]

    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]}]
} -cleanup {
    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 {
    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]]]

    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]}]
} -cleanup {
    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 {
    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}]
    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 {
    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 {
    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}]
    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 {
    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 {
    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}]
    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 {
    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 {


    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}]
    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 {
    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 {
    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}]
    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 {
    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 {
    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 \
		 -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 {
    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 {
    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]
    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 {
    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 {
    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]
    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]}]
} -cleanup {
    http::cleanup $tok
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} gzip chunked gzip,deflate,compress 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.







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|






|



|






|
>

|

|

|





>
>
>
>
>
>
>
>
>
>
>
>
>



|



|
>
>








|



|








|



|








|



|






|
>

|

|

|








|



|








|



|








|



|





>
>
>
>
>
>
>
>
>
>
>
>
>



|



|
>
>








|



|








|



|
















|
|




















|











|





|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






|



|

|



|








|





|
>
>













|





|













|





|


















|






|


















|






|













|





|













|





|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|





|
>
>













|





|













|





|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|





|













|





|













|



|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
    if {$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.$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 {
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close}

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}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding] [meta $tok transfer-encoding] \
        [http::meta $tok content-encoding] [http::meta $tok transfer-encoding]
} -cleanup {
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok gzip {} {content-encoding gzip} {}}

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}]
    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.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.$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}]
    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 compress {}}

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}]
    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 {} {}}

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}]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok content-encoding]
} -cleanup {
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {}}

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]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok connection] [meta $tok transfer-encoding] \
        [http::meta $tok connection] [http::meta $tok transfer-encoding]
} -cleanup {
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close chunked {connection close} {transfer-encoding chunked}}

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]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok connection] [meta $tok transfer-encoding]
} -cleanup {
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok {} chunked}

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]
    http::wait $tok
    list [http::status $tok] [http::code $tok] [check_crc $tok] \
        [meta $tok connection] [meta $tok transfer-encoding]
} -cleanup {
    catch {http::cleanup $tok}
    halt_httpd
} -result {ok {HTTP/1.1 200 OK} ok close {}}

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}]
    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 gzip chunked}

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}]
    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.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.$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}]
    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 compress chunked}

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}]
    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 {} chunked}

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]
    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]]
    set toj [http::geturl http://localhost:$httpd_port/testdoc.html?transfer= \
                 -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]]
    concat $res1 -- $res2
} -cleanup {
    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.$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]
    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]
} -cleanup {
    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.$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}]
    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] -- $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}

# 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.$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}]
    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.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.$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}]
    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 compress chunked}

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}]
    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 {} chunked}

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]]]

    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]}]
} -cleanup {
    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.$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]]]

    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]}]
} -cleanup {
    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.$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}]
    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 {} chunked}

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}]
    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 gzip {} 0}

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}]
    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]}]
} -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.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}]
    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 compress {} 0}

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}]
    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 {} {} 0}

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 \
		 -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]}]
} -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.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]
    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 {} {} chunked}

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]
    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]}]
} -cleanup {
    catch {http::cleanup $tok}
    close $chan
    removeFile testfile.tmp
    halt_httpd
} -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

    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 {
    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]]]
    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]}]
} -cleanup {
    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 {
    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]]]
    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]}]
} -cleanup {
    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 {
    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]]]
    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]}]
} -cleanup {
    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 {
    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]]]
    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]}]
} -cleanup {
    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 {
    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]]]
    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]}]
} -cleanup {
    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 {
    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]]]
    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]}]
} -cleanup {
    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 {
    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]]]
    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]}]
} -cleanup {
    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 {
    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]]]
    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]}]
} -cleanup {
    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 {
    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 {}}]
    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]]}]
} -cleanup {
    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 {
    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 {}}]
    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]]}]
} -cleanup {
    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 {
    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]
    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]
} -cleanup {
    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 {
    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]
    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]
} -cleanup {
    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 {
    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]
    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]
} -cleanup {
    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 {
    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]
    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]
} -cleanup {
    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

unset -nocomplain httpd_port httpd p


::tcltest::cleanupTests








|











|




|












|




|












|




|












|














|











|





|











|




|















|




|















|




|















|




|















|




|











|



|












|



|












|



|















|


















>


>
|
>
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.$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]]]
    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]}]
} -cleanup {
    catch {http::cleanup $tok}
    unset -nocomplain testdata
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0}

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]]]
    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]}]
} -cleanup {
    catch {http::cleanup $tok}
    unset -nocomplain testdata
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0}

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]]]
    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]}]
} -cleanup {
    catch {http::cleanup $tok}
    unset -nocomplain testdata
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0}

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]]]
    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]}]
} -cleanup {
    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.$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]]]
    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]}]
} -cleanup {
    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.$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]]]
    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]}]
} -cleanup {
    catch {http::cleanup $tok}
    unset -nocomplain testdata ::WaitHere
    halt_httpd
} -result {ok {HTTP/1.0 200 OK} ok close {} {} 0}

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]]]
    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]}]
} -cleanup {
    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.$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]]]
    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]}]
} -cleanup {
    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.$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 {}}]
    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]]}]
} -cleanup {
    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.$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 {}}]
    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]]}]
} -cleanup {
    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.$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]
    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]
} -cleanup {
    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.$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]
    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]
} -cleanup {
    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.$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]
    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]
} -cleanup {
    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.$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]
    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]
} -cleanup {
    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
}

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
# httpPipeline.test
#
#	Test HTTP/1.1 concurrent requests including
#	queueing, pipelining and retries.
#
# Copyright (C) 2018 Keith Nash <[email protected]>
#
# 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




































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 -





|









|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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 © 2018 Keith Nash <[email protected]>
#
# 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

# ------------------------------------------------------------------------------
# (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 -
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
	    # End of custom code.
	    # ------------------------------------------------------------------

            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] {
		# Restore default values for tests:
		http::config -pipeline 1 -postfresh 0 -repost 1
                http::init
                set http::http(uid) 0
		SetTestEof {TE}







|







846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
	    # End of custom code.
	    # ------------------------------------------------------------------

            set name "pipeline test header $header footer $footer delay $delay $tag$suffix"


	    # Here's the test:
            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
		SetTestEof {TE}
861
862
863
864
865
866
867

868

# ------------------------------------------------------------------------------


unset header footer delay label suffix match cons name te
namespace delete ::httpTest
namespace delete ::httpTestScript


::tcltest::cleanupTests








>
|
>
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
}

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
# httpTest.tcl
#
#	Test HTTP/1.1 concurrent requests including
#	queueing, pipelining and retries.
#
# Copyright (C) 2018 Keith Nash <[email protected]>
#
# 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.
# ------------------------------------------------------------------------------





|







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 © 2018 Keith Nash <[email protected]>
#
# 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.
# ------------------------------------------------------------------------------

Changes to tests/httpTestScript.tcl.

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 <[email protected]>
#
# 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.





|







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 © 2018 Keith Nash <[email protected]>
#
# 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.

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
# 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.
#
# 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 {{} {
    upvar 1 env(TRAVIS_OSX_IMAGE) travis
    return [expr {![info exists travis] || ![string match xcode* $travis]}]
}}]
testConstraint sqlite3 [expr {[testConstraint notOSXtravis] && ![catch {
    package require sqlite3
}]}]
testConstraint cookiejar [expr {[testConstraint sqlite3] && ![catch {
    package require cookiejar
}]}]

set COOKIEJAR_VERSION 0.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
# 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 © 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 notMacCI [expr {![info exists ::env(MAC_CI)]}]



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
# -*- tcl -*-
#
# The httpd_ procedures implement a stub http server.
#
# Copyright (c) 1997-1998 Sun Microsystems, Inc.
# Copyright (c) 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
} 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]




|
|






|
|
>
|
<
<
<







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 © 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

# 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




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
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]]
}

# 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




	} else {
	    httpdError $sock 400
	    httpd_log $sock Error "bad first line:$line"
	    httpdSockDone $sock
	}
	return
    } elseif {$data(state) == "mime"} {







|


















>
>
>
>







46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
    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"} {

Changes to tests/httpd11.tcl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 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 <[email protected]>
#
# 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-

proc ::tcl::dict::get? {dict key} {
    if {[dict exists $dict $key]} {
        return [dict get $dict $key]
    }
    return
}





|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# httpd11.tcl --                                                -*- tcl -*-
#
#	A simple httpd for testing HTTP/1.1 client features.
#	Not suitable for use on a internet connected port.
#
# Copyright © 2009 Pat Thoyts <[email protected]>
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

package require Tcl

proc ::tcl::dict::get? {dict key} {
    if {[dict exists $dict $key]} {
        return [dict get $dict $key]
    }
    return
}
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    switch -exact -- $compression {
        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]
    while {[string length [set chunk [$chunker]]]} {
        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] }
    }

    set chunker [make-chunk-generator $data 512]
    while {[string length [set chunk [$chunker]]]} {
        puts -nonewline $ochan $chunk
    }
    return
}

proc mime-type {filename} {







|













|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    switch -exact -- $compression {
        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 671]
    while {[string length [set chunk [$chunker]]]} {
        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] }
    }

    set chunker [make-chunk-generator $data 671]
    while {[string length [set chunk [$chunker]]]} {
        puts -nonewline $ochan $chunk
    }
    return
}

proc mime-type {filename} {
146
147
148
149
150
151
152
153




154
155
156
157
158
159
160
161
162






163
164
165
166
167
168
169
170
171
172
173

174
175
176
177
178
179
180

181
182
183
184
185
186
187
        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"}]
        }

        if {$protocol eq "HTTP/1.1"} {
	    foreach enc [split [dict get? $meta accept-encoding] ,] {
		set enc [string trim $enc]






		if {$enc in {deflate gzip compress}} {
		    set encoding $enc
		    break
		}
	    }
            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
        }

        chan configure $chan -buffering line -encoding iso8859-1 -translation crlf







|
>
>
>
>









>
>
>
>
>
>











>







>







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
        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
            } 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"} {
	    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 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
207
208
209
210
211
212
213









214
215




216
217
218
219
220
221
222
223
224
        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
        }

        if {$close} {
            chan event $chan readable {}
            close $chan







>
>
>
>
>
>
>
>
>

|
>
>
>
>
|
|







219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
        if {$transfer eq "chunked"} {
            Puts $chan "transfer-encoding: chunked"
        }
        puts $chan ""
        flush $chan

        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

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.
#
# 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
    }
}


#
# 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
# 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.
#
# 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::*








|
|
|







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 © 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
# 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.
#
# 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::*






|
|







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 © 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
		    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]
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 3
    }
    return $a
} -cleanup {
    unset a







|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
		    set i $i
		    set i [lindex $s $i]
		}
		if {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		incr i -1
	    }
	}
	set a 3
    }
    return $a
} -cleanup {
    unset a
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]
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 3
    } elseif 1<2 then { #; this if arm should be taken
	set a 4
	while {$a != "xxx"} {
	    break;







|







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]
		}
		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
		    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]
	    }
	}
	set a 5
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 6
    }
    return $a
} -cleanup {
    unset a







|







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]
		}
		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
		    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]
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 3
    } elseif 1==2 then { #; this if arm should be taken
	set a 4
	while {$a != "xxx"} {
	    break;







|







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]
		}
		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
		    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]
	    }
	}
	set a 5
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 6
    } else {
	set a 7
	while {$a != "xxx"} {
	    break;







|







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]
		}
		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
		    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]
	    }
	}
	set a 8
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		if {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 9
    }
    return $a
} -cleanup {
    unset a







|







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]
		}
		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
		    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]
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 3
    }
    return $a
} -cleanup {
    unset a z







|







732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
		    set i $i
		    set i [lindex $s $i]
		}
		$z {[string compare $a "bar"] < 0} {
		    set i $i
		    set i [lindex $s $i]
		}
		incr i -1
	    }
	}
	set a 3
    }
    return $a
} -cleanup {
    unset a z
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]
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 3
    } elseif 1<2 then { #; this if arm should be taken
	set a 4
	while {$a != "xxx"} {
	    break;







|







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]
		}
		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
		    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]
	    }
	}
	set a 5
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 6
    }
    return $a
} -cleanup {
    unset a z







|







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]
		}
		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
		    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]
	    }
	}
	set a 2
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 3
    } elseif 1==2 then { #; this if arm should be taken
	set a 4
	while {$a != "xxx"} {
	    break;







|







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]
		}
		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
		    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]
	    }
	}
	set a 5
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 6
    } else {
	set a 7
	while {$a != "xxx"} {
	    break;







|







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]
		}
		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
		    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]
	    }
	}
	set a 8
	while {$a != "xxx"} {
	    break;
	    while {$i >= 0} {
		$z {[string compare $a "bar"] < 0} {







|







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]
		}
		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
		    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]
	    }
	}
	set a 9
    }
    return $a
} -cleanup {
    unset a z







|







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]
		}
		incr i -1
	    }
	}
	set a 9
    }
    return $a
} -cleanup {
    unset a z
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
       upvar 1 $name var
       if {[incr counter] % 2 == 1} {
           set var "$counter oops [concat $extraargs]"
       } else {
           set var "$counter + [concat $extraargs]"
       }
    }
    trace variable iftracevar r [list iftraceproc 10]
    list [catch {if "$iftracevar + 20" {}} a] $a \
        [catch {if "$iftracevar + 20" {}} b] $b
} -cleanup {
    unset iftracevar iftracecounter a b
} -match glob -result {1 {*} 0 {}}

# cleanup







|







1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
       upvar 1 $name var
       if {[incr counter] % 2 == 1} {
           set var "$counter oops [concat $extraargs]"
       } else {
           set var "$counter + [concat $extraargs]"
       }
    }
    trace add variable iftracevar read [list iftraceproc 10]
    list [catch {if "$iftracevar + 20" {}} a] $a \
        [catch {if "$iftracevar + 20" {}} b] $b
} -cleanup {
    unset iftracevar iftracecounter a b
} -match glob -result {1 {*} 0 {}}

# cleanup

Changes to tests/incr-old.test.

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.
#
# 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::*








|
|
|







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 © 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
} {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
    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} {







|







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 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} {

Changes to tests/incr.test.

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.
#
# 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::*






|
|







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 © 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/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
# This file is a Tcl script to test out the 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.
#
# 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]]

testConstraint testindexobj [llength [info commands testindexobj]]

testConstraint testparseargs [llength [info commands testparseargs]]



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}
|



|
|










|


>

>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 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 © 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 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}]
testConstraint has32BitLengths [expr {$tcl_platform(pointerSize) == 4}]

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
    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?\""
test indexObj-5.2 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 2 "bar" mycmd foo
} "wrong # args: should be \"mycmd foo bar\""
test indexObj-5.3 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 0 "bar" mycmd foo
} "wrong # args: should be \"bar\""
test indexObj-5.4 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 0 "" mycmd foo
} "wrong # args: should be \"\""
test indexObj-5.5 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 1 "" mycmd foo
} "wrong # args: should be \"mycmd\""
test indexObj-5.6 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 2 "" 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\""

test indexObj-6.1 {Tcl_GetIndexFromObjStruct} testindexobj {
    set x a
    testgetindexfromobjstruct $x 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\""
test indexObj-6.3 {Tcl_GetIndexFromObjStruct} testindexobj {
    set x c
    testgetindexfromobjstruct $x 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-7.1 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs
} {0 1 testparseargs}
test indexObj-7.2 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -bool
} {1 1 testparseargs}
test indexObj-7.3 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -bool bar
} {1 2 {testparseargs bar}}
test indexObj-7.4 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs bar
} {0 2 {testparseargs bar}}
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}
test indexObj-7.6 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -- -bool -help
} {0 3 {testparseargs -bool -help}}
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}}





































































# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|


|


|


|


|


|




|




|




|



|




>
>
>
>
>
>
>
>
>
>
>
>
|



|


|


|


|



|
>
>
|
|


|


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
    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?"}
test indexObj-5.2 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 2 "bar" mycmd foo
} {wrong # args: should be "mycmd foo bar"}
test indexObj-5.3 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 0 "bar" mycmd foo
} {wrong # args: should be "bar"}
test indexObj-5.4 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 0 "" mycmd foo
} {wrong # args: should be ""}
test indexObj-5.5 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 1 "" mycmd foo
} {wrong # args: should be "mycmd"}
test indexObj-5.6 {Tcl_WrongNumArgs} testindexobj {
    testwrongnumargs 2 "" 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"}

test indexObj-6.1 {Tcl_GetIndexFromObjStruct} testindexobj {
    set x a
    testgetindexfromobjstruct $x 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"}
test indexObj-6.3 {Tcl_GetIndexFromObjStruct} testindexobj {
    set x c
    testgetindexfromobjstruct $x 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 {} -1 32\""

test indexObj-7.1 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs
} {0 1 testparseargs NULL NULL}
test indexObj-7.2 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -bool
} {1 1 testparseargs NULL NULL}
test indexObj-7.3 {Tcl_ParseArgsObjv} testparseargs {
    testparseargs -bool bar
} {1 2 {testparseargs bar} NULL NULL}
test indexObj-7.4 {Tcl_ParseArgsObjv} testparseargs {
    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
 -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} 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} 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} -constraints {
    testgetintforindex has64BitLengths
} -body {
    testgetintforindex end+1 -1
} -result 9223372036854775807
test indexObj-8.14.32bits {Tcl_GetIntForIndex end+1} -constraints {
    testgetintforindex has32BitLengths
} -body {
    testgetintforindex end+1 -1
} -result 2147483647
test indexObj-8.15 {Tcl_GetIntForIndex end+1} testgetintforindex {
    testgetintforindex end+1 -2
} -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
# -*- 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
#
# 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]]
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}








|
|
|
|











|







1
2
3
4
5
6
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 © 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 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}

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]]
} {9 9}

proc testinfocmdcount {} {
    set x [info cmdcount]
    set y 12345
    set z [info cmdc]
    expr {$z-$x}







|
|







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 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}
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
        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
    }
    proc t2 {x y} {
        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}}}}}}







|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
        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
    }
    proc t2 {x y} {
        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}}}}}}
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
    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"}))} {
    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}
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}
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}
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}

##
# ### ### ### ######### ######### #########
## info frame

## Helper
# For the more complex results we cut the file name down to remove path







|




















|


|


|


|







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
    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"}))} {
    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, 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, 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, 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, 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

Changes to tests/init.test.

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.
#
# 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::*






|
|







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 © 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::*
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
		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}
	}] {    ;# 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 \
		"[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








|














|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
		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, , 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 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
# 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).
#
# 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






|







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 © 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
	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:
		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):







|







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 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):

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
# 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.
#
# 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]]

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}

foreach i [interp children] {
  interp delete $i






|
|










|







1
2
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 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 © 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]]

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}

foreach i [interp children] {
  interp delete $i
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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
} 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
} 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







|








|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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}
} 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}
} 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
} 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
} 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 foo
} 8
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} 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"}








|





|


|





|







220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
} 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}}
} 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 foo
} 8
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} 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
} ""
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
    after 200
    update
    interp exists xxx
} 0

#
# Alias loop prevention testing.







|







742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
} ""
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}
    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
    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 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} {







|







962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
    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 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} {
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
} -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 ...?"
    while executing
"coroutine"
    invoked from within
"child invokehidden coroutine"}

test interp-21.1 {interp hidden} {
    interp hidden {}







|







1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
} -body {
    child hide coroutine
    catch {child invokehidden coroutine} m o
    dict get $o -errorinfo
} -cleanup {
    unset -nocomplain m 0
    interp delete child
} -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 {}
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
} {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} {
    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} {
    interp create moo
    set result [catch {interp recursionlimit moo -1} msg]
    interp delete moo
    list $result $msg
} {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]
    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} {
    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} {
    interp create moo
    set result [catch {moo recursionlimit -1} msg]
    interp delete moo
    list $result $msg
} {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]
    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} {







|




|
|




|


|















|




|
|




|


|







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
} {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} -body {
    interp create moo
    set result [catch {interp recursionlimit moo 0} msg]
    interp delete moo
    list $result $msg
} -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
} -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)<<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} -body {
    interp create moo
    set result [catch {moo recursionlimit 0} msg]
    interp delete moo
    list $result $msg
} -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
} -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)<<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} {
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
	    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 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







|







3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
	    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 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
	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 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 {}
}







|
|







3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
	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 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
	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 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
	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 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
	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 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}]
	    trapToParent
	}
    }
    proc cb3 {} {
	global i subi
	interp alias [list $i $subi] foo {} cb4
	interp delete $i







|


















|







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
	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 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}]
	    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
    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 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
    $i eval {
	set x {}
	vwait x
    }
} -cleanup {
    interp delete $i
} -returnCodes error -result {limit exceeded}







|














|







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
    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 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
    $i eval {
	set x {}
	vwait x
    }
} -cleanup {
    interp delete $i
} -returnCodes error -result {limit exceeded}
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
	    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} {
	global result
	lappend result cb1
	$i limit time -seconds $t -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 ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    }
	}







|












|
|







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
	    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} -constraints knownBug -setup {
    proc cb1 {i t} {
	global result
	lappend result cb1
	$i limit time -seconds $t -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 ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    }
	}
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
	lappend result cb1
	set times [lassign $times t]
	$i limit time -seconds $t
    }
} -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 ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    }
	}







|
|







3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
	lappend result cb1
	set times [lassign $times t]
	$i limit time -seconds $t
    }
} -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 ::result {}
    lappend ::result [catch {
	$i eval {
	    for {set i 0} {$i<30} {incr i} {
		after 100
	    }
	}
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
    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}
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}
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}







|











|







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
    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 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 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}
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626

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)}]
} -cleanup {
    unset -nocomplain result
    interp delete a
} -result {26 26}

test interp-38.1 {interp debug one-way switch} -setup {
    catch {interp delete a}







|
|







3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626

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)}}]
} -cleanup {
    unset -nocomplain result
    interp delete a
} -result {26 26}

test interp-38.1 {interp debug one-way switch} -setup {
    catch {interp delete a}

Changes to tests/io.test.

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.
#
# 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
}








|
|
|







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 © 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
    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 tcltests


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]]



testConstraint knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]
testConstraint notOSX [expr {$::tcl_platform(os) ne "Darwin"}]



# 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.







|
|

|

>







>
>
>
|

>
>







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
    variable n
    variable v
    variable msg
    variable expected

    catch {
	::tcltest::loadTestedCommands
	package require -exact tcl::test [info patchlevel]
	set ::tcltestlib [info loaded {} Tcltest]
    }
    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 {
    $::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.
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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
    fileevent $f readable "foo $f"
    proc foo {f} {
	set x [read $f]
	catch {puts -nonewline $x}
	if {[eof $f]} {
	    close $f







|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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
    fileevent $f readable "foo $f"
    proc foo {f} {
	set x [read $f]
	catch {puts -nonewline $x}
	if {[eof $f]} {
	    close $f
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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 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"
    close $f
    contents $path(test1)
} "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"
    close $f
    contents $path(test1)
} "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"

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.








|


|



|


|













|







107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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\x4D\x00"
    close $f
    contents $path(test1)
} "a\x4D\x00"
test io-1.7 {Tcl_WriteChars: WriteChars} {
    set f [open $path(test1) w]
    fconfigure $f -encoding shiftjis
    puts -nonewline $f "a\x00"
    close $f
    contents $path(test1)
} "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"

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
    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}














































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
    puts $f "abcdefghijklmnopqrstuvwxyz"







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
    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
    puts $f "abcdefghijklmnopqrstuvwxyz"
228
229
230
231
232
233
234



















235
236
237
238
239
240
241
     fconfigure $f -encoding binary -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.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"







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
     fconfigure $f -encoding binary -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-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
    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} {
    # stage buffer maps to more than can be queued at once.

    set f [open $path(test1) w]
    fconfigure $f -encoding jis0208 -buffersize 16
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]


} [list "!)!)!)!)!)!)!)!)" "!)!)!)!)!)!)!)!)!)!)!)!)!)!)!)"]
test io-3.5 {WriteChars: saved != 0} {
    # 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
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]


} [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
    # 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.

    set f [open $path(test1) w]
    fconfigure $f -encoding shiftjis -buffersize 16
    puts -nonewline $f "12345678901234\uff21\uff22"
    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)} {
    # 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
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]


} [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-4.1 {TranslateOutputEOL: lf} {
    # search for \n

    set f [open $path(test1) w]
    fconfigure $f -buffering line -translation lf
    puts $f "abcde"







|



|




>
>
|
|





|




>
>
|





|


|



|




|







|




>
>
|









>
>
>
>
>
>
>
>
>







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
    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} -body {
    # stage buffer maps to more than can be queued at once.

    set f [open $path(test1) w]
    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}
} -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 -profile tcl8
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {close $f}
} -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  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  plus the all of ) appended.

    set f [open $path(test1) w]
    fconfigure $f -encoding shiftjis -buffersize 16
    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)} -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 -profile tcl8
    puts -nonewline $f "\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"
    set x [list [contents $path(test1)]]
    close $f
    lappend x [contents $path(test1)]
} -cleanup {
    catch {close $f}
} -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"
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
    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"
    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"
    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"]
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]







|










|






|







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
    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\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"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis
    set x [list [gets $f line] $line]
    close $f
    set x
} [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
    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"
    close $f
    set f [open $path(test1)]
    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"
    close $f
    set f [open $path(test1)]
    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]







|


|






|


|







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
    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"
    close $f
    set f [open $path(test1)]
    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\x1Abat"
    close $f
    set f [open $path(test1)]
    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
    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"
    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"
    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()







|
















|







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
    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"
    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"
    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
    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"
    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)








|







1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
    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"
    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
    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"
    close $f
    set f [open $path(test1)]
    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








|


|







1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
    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"
    close $f
    set f [open $path(test1)]
    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
    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"
    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"]
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 {}







|






|







1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
    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 "thereok\nmore 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 "thereok" 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
} {{} 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"
    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"
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"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis
    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"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis
    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 ""]
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 -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
    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]

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"







|






|





|


|







|


|





|



|














|







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
} {{} 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 "123456789012301234\nend"
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding shiftjis -buffersize 16
    set x [gets $f]
    close $f
    set x
} "123456789012301234"
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"
    close $f
    set f [open $path(test1)]
    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"
    close $f
    set f [open $path(test1)]
    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 16 "123456789012301\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 -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
    puts $f "\x51\x82\x52"
    fconfigure $f -encoding shiftjis
    vwait [namespace which -variable x]
    close $f
    set x
} [list -1 "" 1 17 "12345678901230123" 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"
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
    # 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"
    lappend x [gets $f line] $line
    close $f
    set x
} {15 abcdefghijklmno 1 -1 {}}

test io-9.1 {CommonGetsCleanup} emptyTest {
} {}







|







1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
    # 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"
    lappend x [gets $f line] $line
    close $f
    set x
} {15 abcdefghijklmno 1 -1 {}}

test io-9.1 {CommonGetsCleanup} emptyTest {
} {}
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
	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"
    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]
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"
	gets stdin; puts -nonewline "\x89"
	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
	}







|





|



|

|







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
	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"
    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 "" 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"
	gets stdin; puts -nonewline "\x89"
	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
    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 {}"
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
            }
        }
    }
    set c [chan create read [namespace which driver]]
    chan configure $c -encoding utf-8
    while {![eof $c]} {
        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
            }
        }
    }
    set c [chan create read [namespace which driver]]
    chan configure $c -encoding utf-8
    while {![eof $c]} {
        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
    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} {
    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 -buffersize 10
    set in [read $f]









    close $f




    scan [string index $in end] %c
} 194



test io-12.10 {ReadChars: multibyte chars split} {
    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 -buffersize 11
    set in [read $f]
    close $f
    scan [string index $in end] %c
} 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)]







|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|




|





|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|




|






|







|


|


|

>
>
>
>
>
>
>
>
>

>
>
>
>

|
>
>
>
|


|


|



|
>
>







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
    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  {} 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  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
    }
    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  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
    }
    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
    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} -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 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
} -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
    close $f
    set f [open $path(test1)]
    fconfigure $f -encoding utf-8 -profile tcl8 -buffersize 10
    set in [read $f]
    close $f
    scan [string index $in end] %c
} -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
    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')

    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')

    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







|












|







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
    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 != '\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 != '\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
    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]
	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]
    }







|







2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
    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]
	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
# 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]
    x eval {eof stdin}
    lappend l [expr [testchannel refcount stdin] - $l1]
    interp delete x
    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]
    x eval {eof stdout}
    lappend l [expr [testchannel refcount stdout] - $l1]
    interp delete x
    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]
    x eval {eof stderr}
    lappend l [expr [testchannel refcount stderr] - $l1]
    interp delete x
    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]







|

|

|







|

|

|







|

|

|







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
# 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}]
    x eval {eof stdin}
    lappend l [expr {[testchannel refcount stdin] - $l1}]
    interp delete x
    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}]
    x eval {eof stdout}
    lappend l [expr {[testchannel refcount stdout] - $l1}]
    interp delete x
    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}]
    x eval {eof stderr}
    lappend l [expr {[testchannel refcount stderr] - $l1}]
    interp delete x
    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
    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}]
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}}
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]]







|





|







2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
    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
} {{} {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}}
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]]
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
} {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]
    close $f
} {}

# Test flushing. The functions tested here are FlushChannel.

test io-27.1 {FlushChannel, no output buffered} {
    file delete $path(test1)







|







2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
} {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]}
    close $f
} {}

# Test flushing. The functions tested here are FlushChannel.

test io-27.1 {FlushChannel, no output buffered} {
    file delete $path(test1)
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
    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} {
    # 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 {}
	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 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)]"
    } else {
        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)







|

















|













|

|







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
    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 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 {}
	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 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)]"
    } else {
	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)
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
	    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 f [open $path(output) w]
    close $f
    set f [open "|[list [interpreter] pipe]" r+]
    fconfigure $f -blocking off -eofchar {}

    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
    } else {
        set result ok
    }
} ok
test io-28.4 {Tcl_Close} {testchannel} {
    file delete $path(test1)
    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]] \







|














|

|


|

|







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
	    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 f [open $path(output) w]
    close $f
    set f [open "|[list [interpreter] pipe]" r+]
    fconfigure $f -blocking off -eofchar {}

    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
    } else {
	set result ok
    }
} ok
test io-28.4 Tcl_Close testchannel {
    file delete $path(test1)
    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]] \
2365
2366
2367
2368
2369
2370
2371




































































2372
2373
2374
2375
2376
2377
2378
    }
    close $f
    set f [open "|[list [interpreter] $path(script)]" r]
    set l [gets $f]
    close $f
    lsort $l
} {file1 file2}





































































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]







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    }
    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
} debugpurify {
    variable done
    variable res
    after 0 [list coroutine c1 apply [list {} {
	variable done
	set chan [chan create w {apply {args {
	    list initialize finalize watch write configure blocking
	}}}]
	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
} 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
} debugpurify {
    variable done
    variable res
    after 0 [list coroutine c1 apply [list {} {
	variable done
	set chan [chan create r {apply {{cmd chan args} {
	    switch $cmd {
		blocking - finalize {
		}
		watch {
		    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
} 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]
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
    # 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} {
    # 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}







|







3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
    # 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 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
    y eval "fileevent $c readable \{readit $c\}"
    y eval [list close $c]
    update
    close $s
    interp delete x
    interp delete y
} ""






























































































# 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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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
    }
    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]
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]
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
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    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
    puts $f hello\nthere\nand\rhere
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    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
    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
    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]







|















|




















|


|











|



|
















|



















|







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
    }
    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}]
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}]
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
    close $f
    set f [open $path(test1) r]
    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 -translation lf -eofchar \x1A
    puts $f hello\nthere\nand\rhere
    close $f
    set f [open $path(test1) r]
    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 -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 -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]
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
    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"
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 {}
    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 {}
    set l ""
    set x [gets $f]
    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 {}
    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 {}
    set l ""
    set x [gets $f]
    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
    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
    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
    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
    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
    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
    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.







|











|

















|














|













|













|













|













|













|







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
    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"
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 {}
    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 {}
    set l ""
    set x [gets $f]
    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 {}
    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 {}
    set l ""
    set x [gets $f]
    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
    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
    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
    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
    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
    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
    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
    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.
#
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







|







3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
    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 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
    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
    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
    puts $f hello\nthere\nand\rhere
    close $f
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    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
    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
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f







|














|



|



















<
|

















|







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
    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 -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 -translation lf -eofchar \x1A
    puts $f hello\nthere\nand\rhere
    close $f
    set f [open $path(test1) r]
    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 -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 -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
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
    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"
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 {}
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f







|







4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
    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"
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 {}
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
    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"
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 {}
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f







|







4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
    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"
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 {}
    set s [format "abc\ndef\n%cqrs\ntuv" 26]
    puts $f $s
    close $f
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
    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"
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
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    set l ""
    lappend l [gets $f]
    lappend l [gets $f]
    lappend l [eof $f]
    lappend l [gets $f]
    lappend l [eof $f]
    close $f







|








|

















|

















|

















|

















|

















|







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
    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"
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
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    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
    fconfigure $f -translation crlf
    set c ""
    while {[gets $f line] >= 0} {
	append c $line\n
    }
    close $f
    string length $c
} [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]

# 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} {







|


















|







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
    fconfigure $f -translation crlf
    set c ""
    while {[gets $f line] >= 0} {
	append c $line\n
    }
    close $f
    string length $c
} [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}]

# 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} {
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
    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]
		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
            }
        }
    }
} -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]
		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
            }
        }
    }
} -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
            }
        }
    }
} -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







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|











|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|











|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







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
    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]
		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
	    }
	}
    }
} -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]
		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
	    }
	}
    }
} -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
	    }
	}
    }
} -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
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
    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} {
    file delete $path(test3)
    set f [open $path(test3) w]
    fconfigure $f -encoding binary
    set l ""
    lappend l [tell $f]
    puts -nonewline $f abcdef
    lappend l [tell $f]







|







4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
    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 extensive} {
    file delete $path(test3)
    set f [open $path(test3) w]
    fconfigure $f -encoding binary
    set l ""
    lappend l [tell $f]
    puts -nonewline $f abcdef
    lappend l [tell $f]
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
    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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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}
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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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}
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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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}
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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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}
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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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}
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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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}
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 {}
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    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)







|




|




|



|




|




|



|




|




|



|




|




|



|




|




|



|




|




|









|














|














|














|














|














|







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
    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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation lf -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation cr -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation auto -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    fconfigure $f -translation crlf -eofchar \x1A
    set l [string length [read $f]]
    set e [eof $f]
    close $f
    list $s $l $e
} {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 {}
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    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 {}
    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
    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
    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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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}
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
    puts $f {}
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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}
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)]







|




|




|



|




|




|







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
    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
    puts $f abc\ndef
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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 {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
    puts $f {}
    close $f
    set s [file size $path(test1)]
    set f [open $path(test1) r]
    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 {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)]
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
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    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
    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 {}
    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
    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







|














|







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
    set f [open $path(test1) w]
    fconfigure $f -translation cr -eofchar {}
    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
    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 {}
    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
    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
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
    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
	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







|
|







5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
    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
	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
    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
	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







|
|







5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
    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
	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
    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
    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







|















<
<
<







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
    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 -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 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
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
    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
    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
    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} {
    file delete $path(test1)
    set f [open $path(test1) w]
    set result [list [catch {fconfigure $f -encoding foobar} msg] $msg]

    close $f
    set result
} {1 {unknown encoding "foobar"}}







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"
    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
    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"
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







|






|




|






|
|


|
>

<
|
>
>
>
>
>
>
>



|

















|







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
    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
    close $f
    set f [open $path(test1) r]
    fconfigure $f -encoding utf-8
    set x [read $f]
    close $f
    set x
} 
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
    close $f
    set f [open $path(test1) r]
    fconfigure $f -encoding utf-8
    set x [read $f]
    close $f
    set x
} 
test io-39.16 {Tcl_SetChannelOption: -encoding (shortened to "-en"), errors} -body {
    file delete $path(test1)
    set f [open $path(test1) w]
    fconfigure $f -en foobar
} -cleanup {
    close $f

} -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"
    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
    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"
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
    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} {
    file delete $path(test1)
    set f1 [open $path(test1) w+]
    set l ""
    lappend l [fconfigure $f1 -eofchar]
    fconfigure $f1 -eofchar {ON GO}
    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} {
    file delete $path(test1)
    set f1 [open $path(test1) w+]
    set l [list]
    fconfigure $f1 -eofchar {ON GO}
    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}}}
test io-39.23 {Tcl_GetChannelOption, server socket is not readable or
        writeable, 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}
test io-39.24 {Tcl_SetChannelOption, server socket is not readable or
        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}

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} {
    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]]
    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} {
    # 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}]]
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}]







|




|





|
|



|






|

|





|

|






|
















|



|







|





|
|







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
    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} -constraints {unix deprecated} -body {
    file delete $path(test1)
    set f1 [open $path(test1) w+]
    set l ""
    lappend l [fconfigure $f1 -eofchar]
    fconfigure $f1 -eofchar {O {}}
    lappend l [fconfigure $f1 -eofchar]
    fconfigure $f1 -eofchar D
    lappend l [fconfigure $f1 -eofchar]
    close $f1
    set l
} -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 {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
} -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
	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}
test io-39.24 {Tcl_SetChannelOption, server socket is not readable or
	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}

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 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}]]
    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 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 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}]
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
} -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}}

test io-41.1 {Tcl_FileeventCmd: errors} {fileevent} {
    list [catch {fileevent foo} msg] $msg
} {1 {wrong # args: should be "fileevent channelId 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?"}}







|







6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
} -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 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?"}}
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?"}}
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
    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"
    lappend result [string length [fileevent $f readable]]
    fileevent $f r "new scr\0ipt"
    lappend result [string length [fileevent $f readable]]
    fileevent $f r "yet ano\0ther"
    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} {







|

|

|







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\x00ipt"
    lappend result [string length [fileevent $f readable]]
    fileevent $f r "new scr\x00ipt"
    lappend result [string length [fileevent $f readable]]
    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} {
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
    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
    }
} {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
    }
} {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]
    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 $f4 readable {script 4}
    testfevent delete
    set x [list [fileevent $f readable] [fileevent $f2 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}"
    testfevent delete
    set x [list [fileevent $f readable] [fileevent $f2 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 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]]
    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]]
    testfevent delete
    close $f
    set x
} {{script 1} {}}
unset path(foo)
removeFile foo








|
|
|
|





|
|
|
|
|
|
|
|
















|















|



|

















|


|















|
|













|












|







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
    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
    }
} {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
    }
} {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]
    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 $f4 readable {script 4}
    testfevent delete
    set x [list [fileevent $f readable] [fileevent $f2 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}"
    testfevent delete
    set x [list [fileevent $f readable] [fileevent $f2 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 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]]
    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]]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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)







|







6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    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)







|







6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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)







|







6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    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)







|







6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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)







|







6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation auto
    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)







|







6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation lf
    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)







|







6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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)







|







6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation cr
    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)







|







6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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)







|







6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    fconfigure $f -eofchar \x1a -translation crlf
    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)







|







6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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} {







|







6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
	   lappend l [gets $f]
	   incr c
	}
    }
    set c 0
    set l ""
    set f [open $path(test1) r]
    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
    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
    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
    }
    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]







|
|







|







7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
    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 -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
    }
    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
    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
    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
    }
    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
    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
    }
    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
    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
    }
    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]]
    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
    }
    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
    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
    }
    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]







|
|







|







|
|







|







|
|







|







|
|
|






|







|
|







|







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
    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 -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
    }
    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 -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
    }
    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 -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
    }
    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 -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
    }
    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 -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
    }
    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
# 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"
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]








|







7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
# 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 "АА"
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
    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} {
    # 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



    close $in
    close $out

    file size $path(utf8-fcopy.txt)
} 5

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"
    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

    fcopy $in $out



    close $in


    close $out

    file size $path(kyrillic.txt)
} -result 3



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







|
<
<
<








>
>
>


|
<
<
>


|
|


<
<
<


<


|
<
|
>
>
>
|
>
>
|
|
<
|
>
>







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
    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} -constraints fcopy -body {



    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 "*":\


    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 -profile strict
    puts $out АА
    close $out
} -constraints {fcopy} -body {



    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 -profile strict

    catch {fcopy $in $out} cres copts
	return $cres
} -cleanup {
	if {$in in [chan names]} {
		close $in
	}
	if {$out in [chan names]} {
		close $out
	}

    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
    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-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
    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
    }
    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]







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















|
|









|







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
    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 -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
    }
    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
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


    fcopy $in $out -command [namespace code FcopyTestDone]
    variable 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] {
	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 \
		-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]
	    } else {
	        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] {
	vwait [namespace which -variable fcopyTestDone]
    }
    catch {close $in}
    close $out
    # -1=error 0=script error N=number of bytes
    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
    }







>
>


|


















|















|
|














|

|












|





|







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
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]} {
	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]} {
	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 \
		-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]
	    } else {
		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]} {
	vwait [namespace which -variable fcopyTestDone]
    }
    catch {close $in}
    close $out
    # -1=error 0=script error N=number of bytes
    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
		fcopy $b $a -command [list geof $b]
		puts stderr 2COPY
	    }
	    puts stderr ...
	}
	puts stderr SRV
	set l {}
	set srv [socket -server new 9999]

	puts stderr WAITING
	fileevent stdin readable bye
	puts OK
	vwait forever
    }
    # wait for OK from server.
    gets $pipe
    # 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]
    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 {}







|
>


|



|






|
|







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
		fcopy $b $a -command [list geof $b]
		puts stderr 2COPY
	    }
	    puts stderr ...
	}
	puts stderr SRV
	set l {}
	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 $port"
	vwait forever
    }
    # wait for OK from server.
    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 $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
    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} {
    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.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 {
		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
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
            }
        }
    }
    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
            }
        }
    }
    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
            }
        }
    }
    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
            }
        }
    }
    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} {
    # 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"







|


















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
|
|
|
|
|
|
|
|
|
|
|

|
|












|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|















|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|















|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|















|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|














|







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
    set done
} -cleanup {
    close $outChan
    close $inChan
    removeFile out
    removeFile in
} -result {40 bytes copied}
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 {
		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 "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
	    }
	}
    }
    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
	    }
	}
    }
    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
	    }
	}
    }
    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
	    }
	}
    }
    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 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

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]
	exit 1
    }
    proc readit {pipe} {
	variable x
	variable result
	if {[eof $pipe]} {
	    set x [catch {close $pipe} line]







|







8851
8852
8853
8854
8855
8856
8857
8858
8859
8860
8861
8862
8863
8864
8865

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 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
    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}}}

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 =







|







8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
    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 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
    close $f
    set res
} -cleanup {
    removeFile eofchar
} -result {77 = 23431}


# Test the cutting and splicing of channels, this is incidentially 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]







|







8905
8906
8907
8908
8909
8910
8911
8912
8913
8914
8915
8916
8917
8918
8919
    close $f
    set res
} -cleanup {
    removeFile eofchar
} -result {77 = 23431}


# 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

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.
    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]







|







9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163

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 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
    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"
    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]

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 "*"}












































































































































































































































































































































































































































































# ### ### ### ######### ######### #########




























































































































































# cleanup
foreach file [list fooBar longfile script 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







|







|



















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|







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
    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\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\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 -encoding 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 -encoding 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 -encoding 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 -encoding 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 -encoding 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 -eofchar {} \
	    -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 -encoding 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 -eofchar {} \
	    -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 -encoding 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 -eofchar {} \
	    -translation lf -profile strict
} -body {
    set l {}
    lappend l [catch {gets $f}]
    lappend l [tell $f]
    fconfigure $f -encoding 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 -encoding 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 -eofchar {} \
	    -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 -encoding 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 -eofchar {} \
	    -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 -encoding binary
    # \x81 is invalid in utf-8
    puts -nonewline $f A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none -eofchar {} -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 -encoding 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 -encoding 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 -encoding 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 -encoding 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 -encoding 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 -eofchar {} -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 -encoding binary
    puts -nonewline $f A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -buffering none -eofchar {} -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 -encoding binary
    # \x81 is invalid in utf-8
    puts -nonewline $f A\x81
    flush $f
    seek $f 0
    fconfigure $f -encoding utf-8 -blocking 0 -eofchar {} -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 -encoding 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 -eofchar {} \
	-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 -encoding 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 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
# -*- tcl -*-
# Commands covered: open, close, gets, read, puts, seek, tell, eof, flush,
#		    fblocked, fconfigure, open, channel, fcopy

#
# 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.
#
# 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]]

package require tcltests

# Custom constraints used in this file
testConstraint testchannel	[llength [info commands testchannel]]

#----------------------------------------------------------------------

test iocmd-1.1 {puts command} {


|
>





|
|
|








>


|
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


25
26
27
28
29
30
31
# -*- tcl -*-
# Commands covered: open, close, gets, read, puts, seek, tell, eof, flush,
#		    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 © 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 tcl::test [info patchlevel]]



# Custom constraints used in this file
testConstraint testchannel	[llength [info commands testchannel]]

#----------------------------------------------------------------------

test iocmd-1.1 {puts command} {
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    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
    }
    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







|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    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 -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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
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 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" {}]
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
} -cleanup {
    catch {close $f1}
} -result {-blocking 1 -buffering full -buffersize 4096 -encoding utf-16 -eofchar {} -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
    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}}
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 \
		-eofchar {} -encoding binary
    fconfigure $f1
} -cleanup {
    catch {close $f1}
} -result {-blocking 1 -buffering none -buffersize 4040 -encoding binary -eofchar {} -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







|














|






|




|









|







226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
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 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" -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
} -cleanup {
    catch {close $f1}
} -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 -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 {} -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 \
		-eofchar {} -encoding binary
    fconfigure $f1
} -cleanup {
    catch {close $f1}
} -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
} -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 {
    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}]
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}







|











|







290
291
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
} -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 {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 -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
    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-9.1 {eof command} {
    list [catch {eof} msg] $msg $::errorCode
} {1 {wrong # args: should be "eof channelId"} {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}}
test iocmd-9.3 {eof command} {







>
>
>
>







366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
    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}}
test iocmd-9.2 {eof command} {
    list [catch {eof a b} msg] $msg $::errorCode
} {1 {wrong # args: should be "eof channelId"} {TCL WRONGARGS}}
test iocmd-9.3 {eof command} {
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
} "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}}
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}}
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}}
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.11 {POSIX open access modes: BINARY} {

    set f [open $path(test1) {WRONLY BINARY TRUNC}]






    puts $f \u0248		;# gets truncated to \u0048
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation binary
    set result [read -nonewline $f]
    close $f
    set result
} \u0048










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?"}}







|


|



|












|
>

>
>
>
>
>
>
|






|
>
>
>
>
>
>
>
>
>







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
} "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 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, 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, 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.11 {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.12 {POSIX open access modes: BINARY} {
    set f [open $path(test1) {WRONLY BINARY TRUNC}]
    puts $f H
    close $f
    set f [open $path(test1) r]
    fconfigure $f -translation binary
    set result [read -nonewline $f]
    close $f
    set result
} 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
    set fid [open $f rb]
    append d [read $fid]
    close $fid
    return $d
} -cleanup {
    removeFile $f
} -result 341234x6























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"}}







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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
    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"

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

    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} {







|









|
|
|
>

|
<







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 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 "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, r/w mode empty} {
    proc foo {cmd args} { return {initialize finalize watch} }
    set chan [chan create {} foo]
    close $chan
    rename foo {}
} {}

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} {
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
    }
    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 {
    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







|







1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
    }
    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, 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
} -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}
    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 *}}}
test iocmd-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]
    note [fconfigure $c]
    close $c
    rename foo {}
    set res
} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {{} {}} -translation {auto *}}}
test iocmd-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]
    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}}
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]







|





|


|





|


|

|






|







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
} -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}
    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 {} -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 ""}
    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 {} -profile * -translation {auto *}}}
test iocmd-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]
    note [fconfigure $c]
    close $c
    rename foo {}
    set res
} -result {{cgetall rc*} {-blocking 1 -buffering full -buffersize 4096 -encoding * -eofchar {} -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]
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
	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 {
    set res {}
    proc foo {args} {
	oninit; onfinal; track
	return [string repeat snarf 1000]
    }
    set c [chan create {r w} foo]
    notes [inthread $c {







|







2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
	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, 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
	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 *}}}
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 *}}}
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}}
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]







|












|















|







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
	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 *}}}
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 *}}}
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}}
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

    catch {thread::release $tida}
    thread::release $tidb
    set res
} -constraints {testchannel thread notValgrind} \
    -result {Owner lost}












































































































































































































# ### ### ### ######### ######### #########

# ### ### ### ######### ######### #########

rename track {}
# cleanup








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

    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
# -*- 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 <[email protected]>
#                                    <[email protected]>
#
# 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]]

# 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







|











|







1
2
3
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 © 2007 Andreas Kupries <[email protected]>
#                                    <[email protected]>
#
# 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]]

# 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
    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"

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"}







|







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 "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"}
629
630
631
632
633
634
635























































636
637
638
639
640
641
642
                if {[string length $result] == 0} {
                    driver finalize $chan
                }
                return $result
            }
        }
    }
























































# Channel read transform that is just the identity - pass all through
    proc idxform {cmd handle args} {
      switch -- $cmd {
        initialize {
            return {initialize finalize read}
        }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
                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}
        }
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
#
## 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
## variables

proc inthread {chan script args} {
    # Test thread.
    set tid [thread::create -preserved]
    thread::send $tid {load {} Tcltest}








|







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 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
    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
	# 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 {







|







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 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 {
2085
2086
2087
2088
2089
2090
2091
2092


2093






























2094
2095
    vwait ::res
    set res
} -cleanup {
    thread::send $tidb tempdone
    thread::release $tidb
} -result {Owner lost}

# ### ### ### ######### ######### #########

































cleanupTests
return







|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


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
    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
# -*- 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.
# 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]]

namespace eval ::tcl::test::iogt {
    namespace import ::tcltest::*

testConstraint testchannel [llength [info commands testchannel]]

set path(dummy) [makeFile {abcdefghijklmnopqrstuvwxyz0123456789,./?><;'\|":[]\}\{`~!@#$%^&*()_+-=








|
|








|







1
2
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 © 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 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
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
    fcopy $fin $fout
    close $fin
    close $fout
    join $trail \n
} {create/read {} *ignored*
create/write {} *ignored*
query/maxRead {} -1







|
|







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 -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
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"
    # 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 {







|







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 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 {

Changes to tests/join.test.

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.
#
# 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::*






|
|
|







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 © 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
# 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.
#
# 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]]

set minus -
testConstraint testevalex [llength [info commands testevalex]]

# Tests of Tcl_LindexObjCmd, NOT COMPILED

test lindex-1.1 {wrong # args} testevalex {






|
|
|
|










|







1
2
3
4
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 © 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 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
# 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.
#
# 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]]

testConstraint testlink [llength [info commands testlink]]
testConstraint testlinkarray [llength [info commands testlinkarray]]

foreach i {int real bool string} {
    unset -nocomplain $i
}






|
|
|










|







1
2
3
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 © 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 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
    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
    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}
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}







|

|







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 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 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
    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
    testlink update 32 4.0 3 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
    trace vdelete int w x
    return $x
} {{int {} w} 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
    testlink update 32 4.0 6 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
    trace vdelete int w 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







|

|

|









|

|







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 add var int write x
    testlink update 32 4.0 3 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
    trace remove variable int write x
    return $x
} {{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 add var int write x
    testlink update 32 4.0 6 abcd 113355 65 251 30001 60001 0xbabebeef 12322 32124 3.125 12312312340
    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
# 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.
#
# 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::*






|
|
|







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 © 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/list.test.

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.
#
# 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::*






|
|
|







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 © 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
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"
    string equal $l $e
} 1
test list-1.28 {basic null treatment} {
    set result "\0a\0b"
    list $result [string length $result]
} "\0a\0b 4"
test list-1.29 {basic null treatment} {
    set result "\0a\0b"
    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"
    string equal $l $e
} 1

# 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







|
|



|

|

|





|
|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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 "" "\x00" "\x00\x00"]
    set e "{} \x00 \x00\x00"
    string equal $l $e
} 1
test list-1.28 {basic null treatment} {
    set result "\x00a\x00b"
    list $result [string length $result]
} "\x00a\x00b 4"
test list-1.29 {basic null treatment} {
    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 "\x00abc" "xyz"]
    set e "\x00abc xyz"
    string equal $l $e
} 1

# 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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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]
    while {$last > 0} {
	set minIndex [expr [llength $list] - 1]
	set min [lindex $list $last]
	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]
	}
	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 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}








|

|

|





|





|
|

|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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}]
    while {$last > 0} {
	set minIndex [expr {[llength $list] - 1}]
	set min [lindex $list $last]
	set i [expr {$minIndex - 1}]
	while {$i >= 0} {
	    if {[string compare [lindex $list $i] $min] < 0} {
		set minIndex $i
		set min [lindex $list $i]
	    }
	    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 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
# 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.
#
# 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]]

testConstraint testobj [llength [info commands testobj]]





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
} {}








|
|










|


>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 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 © 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]]

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
} {}

191
192
193
194
195
196
197




















198
199
200
201







































































































202
203
204
205
206
207
208
209
	    [testlistobj get 1]
    }
    -cleanup {
	testobj freeallvars
    }
    -result {{a b c d e} {} {a b c d e f}}
}





















test listobj-11.1 {Bug 3598580: Tcl_ListObjReplace refcount management} testobj {
    testobj bug3598580
} 123








































































































# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
# 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.
#
# 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::*






|
|
|







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 © 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
# 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
#
# 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]} {






|
|
|







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 © 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]} {
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    }} 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]
    }
} -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] "







|







353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
    }} 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}]
    }
} -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] "

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
# 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.
#
# 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]]

# 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 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 *pkga* $alreadyLoaded]}]

set alreadyTotalLoaded [info loaded]

# Certain tests require the 'teststaticpkg' command from tcltest

testConstraint teststaticpkg [llength [info commands teststaticpkg]]

# 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-2.1 {basic loading, with guess for package name} \
	[list $dll $loaded] {
    load -global [file join $testDir pkga$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
    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
} -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}}

test load-3.1 {error in _Init procedure, same interpreter} \
	[list $dll $loaded] {
    list [catch {load [file join $testDir pkge$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}}}
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] \
	    $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}}}

test load-4.1 {reloading package into same interpreter} [list $dll $loaded] {
    list [catch {load [file join $testDir pkga$ext] pkga} msg] $msg
} {0 {}}
test load-4.2 {reloading package into same interpreter} -setup {
    catch {load [file join $testDir pkga$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\""

test load-5.1 {file name not specified and no static package: pick default} \
	[list $dll $loaded] {
    catch {interp delete x}
    interp create x

    load -global [file join $testDir pkga$ext] pkga
    load {} pkga x
    set result [info loaded x]

    interp delete x
    set result
} [list [list [file join $testDir pkga$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] {
    set x "not loaded"
    teststaticpkg 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] {
    set x "not loaded"
    teststaticpkg 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] {
    set x "not loaded"
    teststaticpkg 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
    info loaded
} -result [list {{} Double} {{} More} {{} Another} {{} Test} {*}$currentRealPackages {*}$alreadyTotalLoaded]

testConstraint teststaticpkg_8.x \
    [if {[testConstraint teststaticpkg]} {

	teststaticpkg Test 1 1
	teststaticpkg Another 0 1
	teststaticpkg More 0 1
	teststaticpkg Double 0 1
	expr 1
    } else {
	expr 0
    }]


test load-8.1 {TclGetLoadedPackages procedure} [list teststaticpkg_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 {
    info loaded gorp
} -returnCodes error -result {could not find interpreter "gorp"}
test load-8.3a {TclGetLoadedPackages procedure} [list teststaticpkg_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 [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
    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}]
interp delete child

test load-9.1 {Tcl_StaticPackage, load already-loaded package into another interp} \
    -constraints {teststaticpkg} \
    -setup {
	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 }
	list \
	    [child1 eval { info loaded {} }] \
	    [child2 eval { info loaded {} }]
    } \


    -match glob -result {{{{} Loadninepointone} {* Tcltest}} {{{} Loadninepointone} {* Tcltest}}} \
    -cleanup { interp delete child1 ; interp delete child2 }

test load-10.1 {load from vfs} \



    -constraints [list $dll $loaded testsimplefilesystem] \
    -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}




test load-11.1 {Load TclOO extension using Stubs (Bug [f51efe99a7])} \
	[list $dll $loaded] {
    load [file join $testDir pkgooa$ext]
    list [pkgooa_stubsok] [lsort [info commands pkgooa_*]]
} {1 pkgooa_stubsok}

# cleanup
unset ext
::tcltest::cleanupTests
return






|
|










|








|





|




|

|






|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|





|





|




|
|



|







|






|









|


|


|

|
|

|
<


>
|
|
|
>

<
|










|

|




|

|




|
|

|



|
|
|
|
|
|
|
|
|
|
|

|

|
|
>
|
|
|
|
<
|
<
<
|
>
|
>

|
|


|

|
|

|
|
|

|


|
<
<
|
|
|
|
<
|
|
|
<
|
|
|
>
>
|
<

|
>
>
>
|
<
|
|
|
>
>
|
>


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141

142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194

195


196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217


218
219
220
221

222
223
224

225
226
227
228
229
230

231
232
233
234
235
236

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# 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 © 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 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 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 {}]
testConstraint $loaded [expr {![string match *pkga* $alreadyLoaded]}]

set alreadyTotalLoaded [info loaded]

# Certain tests require the 'teststaticlibrary' command from tcltest

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} -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 {couldn't figure out prefix for -global}

test load-2.1 {basic loading, with guess for package name} \
	[list $dll $loaded] {
    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 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 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 tcl9pkga$ext] {} child} msg] $msg
} {1 {can't 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 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 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 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 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 tcl9pkga$ext] Pkga} msg] $msg
} {0 {}}
test load-4.2 {reloading package into same interpreter} -setup {
    catch {load [file join $testDir tcl9pkga$ext] Pkga}
} -constraints [list $dll $loaded] -returnCodes error -body {
    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} -setup {

    catch {interp delete x}
    interp create x
} -constraints [list $dll $loaded] -body {
    load -global [file join $testDir tcl9pkga$ext] Pkga
    load {} Pkga x
    info loaded x
} -cleanup {
    interp delete x

} -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_StaticLibrary procedure} [list teststaticlibrary] {
    set x "not loaded"
    teststaticlibrary Test 1 0
    load {} Test
    load {} Test child
    list [set x] [child eval set x]
} {loaded loaded}
test load-7.2 {Tcl_StaticLibrary procedure} [list teststaticlibrary] {
    set x "not loaded"
    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 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"
    teststaticlibrary More 0 1
    load {} More
    set x
} {not loaded}
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} {*}$currentRealLibraries {*}$alreadyTotalLoaded]

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

	testConstraint teststaticlibrary_8.x 1


    }
}

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} {*}$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 {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 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 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 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_StaticLibrary, load already-loaded package into another interp} -setup {


    interp create child1
    interp create child2
    load {} Tcltest child1
    load {} Tcltest child2

} -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 -cleanup {
    interp delete child1
    interp delete child2
} -result {{{{} Loadninepointone} {* Tcltest}} {{{} Loadninepointone} {* Tcltest}}}


test load-10.1 {load from vfs} -setup {
    set dir [pwd]
    cd $testDir
    testsimplefilesystem 1
} -constraints [list $dll $loaded testsimplefilesystem] -body {

    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 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
# 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.
#
# 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::*






|
|
|







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 © 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/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
# 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.
#
# 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]]

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} {






|
|
|










|







1
2
3
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 © 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 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} {

Changes to tests/lrepeat.test.

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.
#
# 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::*






|







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 © 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
}
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 {
     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}







|







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} -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
# 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.
#
# 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::*






|
|
|







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 © 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::*
229
230
231
232
233
234
235
















































































































































































































































































































236
237
238
239
240
241
242
243
244
245
246
		    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
		}
	    }
	}
















































































































































































































































































































    }
}}

# cleanup
catch {unset foo}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
# 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.
#
# 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::*






|
|
|







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 © 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::*
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
} 2
test lsearch-4.2 {binary data} {
    set x one
    append x \x00
    append x two
    lsearch -exact [list foo one\000two bar] $x
} 1

# Make a sorted list
set l {}
set l2 {}
for {set i 0} {$i < 100} {incr i} {
    lappend l $i







|





|







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\x00two bar] bar
} 2
test lsearch-4.2 {binary data} {
    set x one
    append x \x00
    append x two
    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
    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))]
    lsearch -start $x $x $x
} 0

test lsearch-16.1 {lsearch -regexp shared object} {
    set str a
    lsearch -regexp $str $str
} 0







|







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))}]
    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
} -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





# cleanup
catch {unset res}
catch {unset increasingIntegers}
catch {unset decreasingIntegers}
catch {unset increasingDoubles}







>
>
>







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
# 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 numbers} {
    -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.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}

#
# 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-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 -result {bad operation "foo": must be .., to, count, or by}

test lseq-3.3 {error case} -body {
    lseq 10 foo
} -returnCodes 1 -result {bad operation "foo": must be .., to, count, or by}

test lseq-3.4 {error case} -body {
    lseq 25 or 6
} -returnCodes 1 -result {bad operation "or": must be .., to, count, or by}

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.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}


# 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
# 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.
#
# 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]]

proc failTrace {name1 name2 op} {
    error "trace failed"
}

testConstraint testevalex [llength [info commands testevalex]]









|










|







1
2
3
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 © 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 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
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 {
    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]







|







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 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
# 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.
#
# 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::*








|







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 © 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
# 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.
#
# 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::*






|







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 © 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::*

Changes to tests/macOSXLoad.test.

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.
#
# 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::*






|
|







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 © 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
# 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?
    #	- 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-]}]

    # 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













|
<
<
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21
22
23
24
# 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 tcl::test package loaded?


    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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
    } -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]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile script
    } -result [list script [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u00c0]]] 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]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile script
    } -result [list script [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u20ac]]] 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]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile \u00c0
    } -result [list [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u00c0]]] {} 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]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile \u20ac
    } -result [list [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] \u20ac]]] {} 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]"
	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]"
	close $f
	catch {set f [open "|[list [interpreter] -encoding ascii 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]"
	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
    } -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
    } -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
    } -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
    } -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
    } -body {
	exec [interpreter] << {puts "In script"} \
		-appinitprocclosestderr >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f







|






|






|






|





|
|




|

|





|
|




|

|











|
|




















|

|


















|

















|















|












|















|













|







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
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 À]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile script
    } -result [list script [list [encoding convertfrom [encoding system] \
	[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 ]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile script
    } -result [list script [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] ]]] 0]\n

    test Tcl_Main-1.5 {
    } -constraints {
	stdio
    } -setup {
	makeFile {puts [list $argv0 $argv $tcl_interactive]} À
	catch {set f [open "|[list [interpreter] À]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile À
    } -result [list [list [encoding convertfrom [encoding system] \
	[encoding convertto [encoding system] À]]] {} 0]\n

    test Tcl_Main-1.6 {
    } -constraints {
	stdio
    } -setup {
	makeFile {puts [list $argv0 $argv $tcl_interactive]} 
	catch {set f [open "|[list [interpreter] ]" r]}
    } -body {
	read $f
    } -cleanup {
	close $f
	removeFile 
    } -result [list [list [encoding convertfrom [encoding system] \
	[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  }
	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 "]"
	close $f
	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 "]"
	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 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 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 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 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 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
	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
    } -setup {
	makeFile {
		rename exit _exit
		proc exit {code} {
		    puts "In exit"
		    _exit $code
		}







|







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 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
	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
    } -setup {
	makeFile {
		close stdin
		testsetmainloop
		rename exit _exit
		proc exit {code} {
		    puts "In exit"







|







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 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
	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
    } -setup {
	makeFile {
		rename exit _exit
		proc exit {code} {
		    puts "In exit"
		    _exit $code
		}







|







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 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
	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
    } -setup {
	makeFile {
		testsetmainloop
		rename exit _exit
		proc exit {code} {
		    puts "In exit"
		    _exit $code







|







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 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
    } -result {}

    # Tests Tcl_Main-4.*: rc file evaluation

    test Tcl_Main-4.1 {
	Tcl_Main: rcFile evaluation deletes interp
    } -constraints {
	exec Tcltest
    } -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
    } -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
    } -setup {
	set rc [makeFile {
		close stdin
		testsetmainloop
		after 0 testexitmainloop
		testexithandler create 0
		rename exit _exit







|
















|
















|







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 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 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 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
	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
    } -setup {
	set rc [makeFile {
		testsetmainloop
		after 0 testexitmainloop
		testexithandler create 0
		rename exit _exit
		proc exit code {







|







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 tcl::test
    } -setup {
	set rc [makeFile {
		testsetmainloop
		after 0 testexitmainloop
		testexithandler create 0
		rename exit _exit
		proc exit code {
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
	removeFile rc
    } -result "application-specific initialization failed:\
	\nExit MainLoop\nIn exit\neven 0\n"

    test Tcl_Main-4.5 {
        Tcl_Main: Bug 1481986
    } -constraints {
        exec Tcltest
    } -setup {
        set rc [makeFile {
                testsetmainloop
                after 0 {puts "Event callback"}
        } rc]
    } -body {
        set f [open "|[list [interpreter] -appinitprocsetrcfile $rc]" w+]







|







544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
	removeFile rc
    } -result "application-specific initialization failed:\
	\nExit MainLoop\nIn exit\neven 0\n"

    test Tcl_Main-4.5 {
        Tcl_Main: Bug 1481986
    } -constraints {
        exec tcl::test
    } -setup {
        set rc [makeFile {
                testsetmainloop
                after 0 {puts "Event callback"}
        } rc]
    } -body {
        set f [open "|[list [interpreter] -appinitprocsetrcfile $rc]" w+]
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
	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"
	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







|
|







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 \\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
	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
    } -body {
	exec [interpreter] << {
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
		}







|







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 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
	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
    } -body {
	exec [interpreter] << {
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
		}







|







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 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
	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
    } -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 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
    } -body {
	exec [interpreter] << {
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
		}







|




















|







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 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 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 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
	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
    } -body {
	exec [interpreter] << {
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code
		}







|







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 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
	close $f
	file delete result
    } -result "1\n% "

    test Tcl_Main-6.2 {
	Tcl_Main: prompt deletes interp
    } -constraints {
	exec Tcltest
    } -body {
	exec [interpreter] << {
		set tcl_prompt1 {testinterpdelete {}}
		set tcl_interactive 1
		puts "not reached"
	} >& result
	set f [open result]







|







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 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
	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
    } -body {
	exec [interpreter] << {
		set tcl_interactive 1
		testsetmainloop
		testexitmainloop} >& result
	set f [open result]
	read $f







|







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 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
    } -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
    } -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
    } -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
    } -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
    } -body {
	exec [interpreter] << {
		testsetmainloop
		testexithandler create 0
		rename exit _exit
		proc exit code {
		    puts "In exit"







|















|



















|
















|







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 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 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 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 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
	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
    } -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
    } -body {
	exec [interpreter] << {
		testsetmainloop
		rename exit _exit
		proc exit code {
		    puts "In exit"
		    _exit $code







|




















|







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 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 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
	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
    } -body {
	exec [interpreter] << {
		testsetmainloop
		set tcl_interactive 1
		rename exit _exit
		proc exit code {
		    puts "In exit"







|







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 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
	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
    } -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
    } -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
    } -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
    } -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
    } -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
    } -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
    } -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
    } -body {
	exec [interpreter] << "testsetmainloop\nputs \\\npwd\ntestexitmainloop" >& result
	set f [open result]
	read $f
    } -cleanup {
	close $f
	file delete result







|


















|
















|

















|















|

















|















|


















|







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 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 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 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 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 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 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 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 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
# 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
#
# 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.
# Byte compiled / non byte compiled version
# Shared / unshared arguments
# Original / imported
proc TestOp {op args} {
    set results {}

    # Non byte compiled version, shared args






|
|
















|







1
2
3
4
5
6
7
8
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: ::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 © 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 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
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
        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
    }
    expr {$exp eq $res ? 1 : "($res != $exp"}
} 1
test mathop-22.3 { bitwise ops } {
    set big1      12135435435354435435342423948763867876







|
|

|







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
        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
    }
    expr {$exp eq $res ? 1 : "($res != $exp"}
} 1
test mathop-22.3 { bitwise ops } {
    set big1      12135435435354435435342423948763867876

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
# 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.
#
# 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]]

testConstraint testhashsystemhash [llength [info commands testhashsystemhash]]

test misc-1.1 {error in variable ref. in command in array reference} {
    proc tstProc {} {
	global a








|
|
|










|







1
2
3
4
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 © 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 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
# 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.
# 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.




|
|







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 © 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.
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
    }
    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 {
	    mcforgetpackage
    	    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 {
	    mcforgetpackage
    	    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 {
	    mcforgetpackage
    	    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 {
	    mcforgetpackage
    	    mclocale $locale
	    mclocale ""
	    mcloadedlocales clear
	    set resultvariable ""
	} -cleanup {
	    mcforgetpackage







|













|

















|












|







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
    }
    set bgerrorsaved [interp bgerror {}]
    interp bgerror {} [namespace code callbackproc]

    variable locale
    if {![info exist locale]} { set locale [mclocale] }

	test msgcat-14.1 {invocation loadcmd} -setup {
	    mcforgetpackage
    	    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 {invocation failed in loadcmd} -setup {
	    mcforgetpackage
    	    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 {invocation changecmd} -setup {
	    mcforgetpackage
    	    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 {invocation unknowncmd} -setup {
	    mcforgetpackage
    	    mclocale $locale
	    mclocale ""
	    mcloadedlocales clear
	    set resultvariable ""
	} -cleanup {
	    mcforgetpackage

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
# 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.
#
# 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::*









|
|
|







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 © 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::*
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
            variable x ""
        }
        variable status ""
        proc monitor {name1 name2 op} {
            variable status
            lappend status "$op: $name1"
        }
        trace variable foo::x rwu [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}}

# -----------------------------------------------------------------------
# TEST: imported commands
# -----------------------------------------------------------------------
test namespace-old-9.1 {empty "namespace export" list} {
    list [catch "namespace export" msg] $msg
} {0 {}}







|





|







631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
            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 }
} {{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 {}}
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
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
} {{} 1 {invalid command name "cmd1"}}
test namespace-old-9.15 {existing commands can't be overwritten} {
    proc cmd1 {x y} {
        return [expr $x+$y]
    }
    list [catch {namespace import test_ns_import::cmd?} msg] $msg \
         [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] }
    list [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?







|





|







749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
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
} {{} 1 {invalid command name "cmd1"}}
test namespace-old-9.15 {existing commands can't be overwritten} {
    proc cmd1 {x y} {
        return [expr {$x+$y}]
    }
    list [catch {namespace import test_ns_import::cmd?} msg] $msg \
         [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}] }
    list [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?

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
# 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.
#
# 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]]

#
# 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_*








|
|











|







1
2
3
4
5
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 © 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 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_*
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
        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.
    child eval {rename ::tcl::info::commands ::infocommands}
    child hide infocommands
    child eval {
	proc foo {} {
	    namespace delete ::
	}
    }







|
|







178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
        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 ::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
	namespace ensemble create
    }

    trace add command ns1 delete {
	namespace delete ns1
    }
} -body {
    # No segmentation fault given --enable-symbols=mem.
    namespace delete ns1
} -result {}































































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







|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
	namespace ensemble create
    }

    trace add command ns1 delete {
	namespace delete ns1
    }
} -body {
    # 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
1853
1854
1855
1856
1857
1858
1859


















1860
1861
1862
1863
1864
1865
1866
    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-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}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    }
} -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 {




    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;#"







|
>
>
>
>







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
    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
    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 {
    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*] {







<
|







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
    }

} -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*] {
3348
3349
3350
3351
3352
3353
3354





































3355
3356
3357
3358
3359
3360
3361
} -body {
    namespace-56.5 cmd
} -cleanup {
    namespace delete namespace-56.5
} -result 1








































test namespace-57.0 {
    an imported alias should be usable in the deletion trace for the alias

    see 29e8848eb976
} -body {
    variable res {}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
} -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
#  -*- 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.
#
# 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]]

testConstraint testevent [llength [info commands testevent]]

test notify-1.1 {Tcl_QueueEvent and delivery of a single event} \
    -constraints {testevent} \
    -body {
	set delivered {}










|










|







1
2
3
4
5
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 © 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 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
# Commands covered:  proc, apply, [interp alias], [namespce 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.
#
# 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]]

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.
#
|





|










|







1
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], [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 © 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 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
# 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.
#
# 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]]

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 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 type 1]
    lappend result [testobj refcount 1]
} {{} 12 12 bytearray 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]







|
|










|








<



















|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 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 © 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]]

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} {

	bytecode
	cmdName
	dict
	regexp
	string
    } {
        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 string]
    lappend result [testobj type 1]
    lappend result [testobj refcount 1]
} {{} 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]
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
    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 [catch {testbooleanobj not 1} msg]
    lappend result $msg
} "1\u7777 1 {expected boolean value but got \"1\u7777\"}"

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}







|


|







246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
    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]
    lappend result [catch {testbooleanobj not 1} msg]
    lappend result $msg
} "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}

Changes to tests/oo.test.

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-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
if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

# 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




|




|







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 © 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 tcl::oo 1.3.0
if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

# 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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
	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
    }
    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
	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







|






|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
	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 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 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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
	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
	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
	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-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







|










|


















|
|
|
|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
	interp delete foo
    }
} 0
test oo-0.6 {cleaning the core class pair; way #1} -setup {
    interp create t
} -body {
    t eval {
	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 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 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
	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}

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
    }
} -body {
    subinterp eval {
	oo::define oo::object constructor {} {
	    lappend ::result [info level 0]
	}
	lappend result 1







|






|







372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
	foreach initial $initials {
	    lappend x [info object class $initial]
	}
	return $x
    }] {lsort [lsearch -all -not -inline $x *::delegate]}
} -cleanup {
    interp delete $fresh
} -result {{} {::oo::Slot ::oo::abstract ::oo::class ::oo::configurable ::oo::configuresupport::configurable ::oo::object ::oo::singleton} {::oo::configuresupport::objreadableproperties ::oo::configuresupport::objwritableproperties ::oo::configuresupport::readableproperties ::oo::configuresupport::writableproperties ::oo::define::filter ::oo::define::mixin ::oo::define::superclass ::oo::define::variable ::oo::objdefine::filter ::oo::objdefine::mixin ::oo::objdefine::variable} {::oo::Slot ::oo::class ::oo::configuresupport::configurable} {::oo::abstract ::oo::configurable ::oo::singleton} {} {} {} {} {} ::oo::object ::oo::object ::oo::class ::oo::class ::oo::class}

test oo-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 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
} -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
    }
} -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
    }
} -body {
    subinterp eval {
	oo::define oo::object destructor {
	    lappend ::result died
	}
	lappend result 1 [oo::object create foo]







|



















|







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
} -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 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 tcl::oo
    }
} -body {
    subinterp eval {
	oo::define oo::object destructor {
	    lappend ::result died
	}
	lappend result 1 [oo::object create foo]
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
    }}}

    rename obj1 {}
    # No segmentation fault
    return done
} done

test oo-11.6.1 {
    OO: cleanup of when an class is mixed into itself
} -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 {
}

test oo-11.6.2 {
    OO: cleanup ReleaseClassContents() where class is mixed into one of its
    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 {
}

test oo-11.6.3 {
    OO: cleanup ReleaseClassContents() where class is mixed into one of its
    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 {
}

test oo-11.6.4 {
    OO: cleanup ReleaseClassContents() where class is mixed into one of its
    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







<
|
<







|
<
<
<
|
<
<










|
<
<
<
|
<
<












|
<
<
<
|
<
<







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
    }}}

    rename obj1 {}
    # No segmentation fault
    return done
} done


test oo-11.6.1 {OO: cleanup of when an class is mixed into itself} -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



test oo-11.6.2 {OO: cleanup ReleaseClassContents() where class is mixed into one of its 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



test oo-11.6.3 {OO: cleanup ReleaseClassContents() where class is mixed into one of its 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



test oo-11.6.4 {OO: cleanup ReleaseClassContents() where class is mixed into one of its 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
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
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}
    }
    [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}
    }
    oo::class create boo {
	superclass foo
	destructor {set ::result "ok"}
    }
    boo new
    foo create bar







|











|







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
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}}
    }
    [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}}
    }
    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
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}
	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}
    }
    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]







|













|







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
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}}
	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}}
    }
    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
    oo::class create cls {
	superclass parent
	mixin mix
	method test {} {lappend ::result cls; next; return $::result}
    }
    [cls new] test
} -result {mix cls}


























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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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
    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}
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] \







|







2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
    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, 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
} -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}
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]







|







2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
} -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, 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]
4193
4194
4195
4196
4197
4198
4199
4200













4201
4202
4203
4204
4205
4206
4207
    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}














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]







|
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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, -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
    }
    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}
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}}
test oo-34.4 {TIP 380: slots - presence} {
    getMethods oo::define::mixin
} {{-append -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}}
test oo-34.6 {TIP 380: slots - presence} {
    getMethods oo::define::variable
} {{-append -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}}
test oo-34.8 {TIP 380: slots - presence} {
    getMethods oo::objdefine::mixin
} {{-append -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}}
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 {







|






|


|


|


|


|


|


|







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
    }
    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::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 -appendifnew -clear -prepend -remove -set} {Get Set}}
test oo-34.4 {TIP 380: slots - presence} {
    getMethods oo::define::mixin
} {{-append -appendifnew -clear -prepend -remove -set} {--default-operation Get Resolve Set}}
test oo-34.5 {TIP 380: slots - presence} {
    getMethods oo::define::superclass
} {{-append -appendifnew -clear -prepend -remove -set} {--default-operation Get Resolve Set}}
test oo-34.6 {TIP 380: slots - presence} {
    getMethods oo::define::variable
} {{-append -appendifnew -clear -prepend -remove -set} {Get Set}}
test oo-34.7 {TIP 380: slots - presence} {
    getMethods oo::objdefine::filter
} {{-append -appendifnew -clear -prepend -remove -set} {Get Set}}
test oo-34.8 {TIP 380: slots - presence} {
    getMethods oo::objdefine::mixin
} {{-append -appendifnew -clear -prepend -remove -set} {--default-operation Get Resolve Set}}
test oo-34.9 {TIP 380: slots - presence} {
    getMethods oo::objdefine::variable
} {{-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 {

Changes to tests/ooNext2.test.

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
#
# 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
if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

testConstraint memory [llength [info commands memory]]
if {[testConstraint memory]} {




|




|







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 © 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 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
	}
    }
    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
	    nextto B $q
	    nextto A $p $r
	}
	method result {} {return $result}
    }
    [C new x y z] result
} -cleanup {







|







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-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
# 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
#
# 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
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





|
|




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 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 © 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 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
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
    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 {
    oo::class create parent
} -body {
    oo::class create xyz {
	superclass parent
	initialise {
	    variable x 1 y 2
	}







|







425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
    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: 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
    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 {
    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 {
    oo::class create parent
} -body {
    oo::class create xyz {
	superclass parent
	method a {} {
	    classvariable ::x
	    incr x







|















|







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
    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: 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: 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
	}
    }
    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 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 }
    }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	}
    }
    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 }
    }

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
# 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.
#
# 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

# 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]"

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}






|
|
|










|









|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 © 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.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}]"

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
# 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
#
# 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]]

# 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::*







|
|
|










|







1
2
3
4
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 © 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 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::*
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"}]
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








|







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"}]
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
# 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.
#
# 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]]

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
} {- 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 {}}




|
|













|













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 © 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 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\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
    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
	#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







|







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}
	#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
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 {}}
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







|
|







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 {}}
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
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]}
} {8}
test parse-10.4 {Tcl_EvalTokens, nested commands} testevalex {
    unset -nocomplain a
    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])}
} {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]}
} {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}







|



|













|


















|







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}]}
} {8}
test parse-10.4 {Tcl_EvalTokens, nested commands} testevalex {
    unset -nocomplain a
    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}])}
} {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}]}
} {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
test parse-12.5 {Tcl_ParseVarName procedure, just a dollar sign} testparsevarname {
    testparsevarname {$abcd} 1 0
} {- {} 0 text {$} 0 abcd}
test parse-12.6 {Tcl_ParseVarName procedure, braced variable name} testparser {
    testparser {${..[]b}cd} 0
} {- {${..[]b}cd} 1 word {${..[]b}cd} 3 variable {${..[]b}} 1 text {..[]b} 0 text cd 0 {}}
test parse-12.7 {Tcl_ParseVarName procedure, braced variable name} testparser {
    testparser "\$\{\{\} " 0
} {- \$\{\{\}\  1 word \$\{\{\} 2 variable \$\{\{\} 1 text \{ 0 {}}
test parse-12.8 {Tcl_ParseVarName procedure, missing close brace} testparser {
    list [catch {testparser "$\{abc" 0} msg] $msg $::errorInfo
} {1 {missing close-brace for variable name} missing\ close-brace\ for\ variable\ name\n\ \ \ \ (remainder\ of\ script:\ \"\{abc\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"\$\\\{abc\"\ 0\"}
test parse-12.9 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {
    list [catch {testparsevarname {${bcd}} 4 0} msg] $msg
} {1 {missing close-brace for variable name}}
test parse-12.10 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {







|
|







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 {}}
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
    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 {
    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} {







|







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 {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
    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
} {- 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 {}}







|







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\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
    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
} {- 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 {}}







|







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\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
    info complete {a b "cd"xyz}
} 1
test parse-15.16 {CommandComplete procedure} {
    info complete {a b "c $d() d"}
} 1
test parse-15.17 {CommandComplete procedure} {
    info complete {a b "c $dd("}
} 0
test parse-15.18 {CommandComplete procedure} {
    info complete {a b "c \"}
} 0
test parse-15.19 {CommandComplete procedure} {
    info complete {a b "c [d e f]"}
} 1
test parse-15.20 {CommandComplete procedure} {







|







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("}
} 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
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"
} 1
test parse-15.56 {CommandComplete procedure} testbytestring {
    info complete "set x [testbytestring \0]; \{"
} 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







|


|







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 \x00]; puts hi"
} 1
test parse-15.56 {CommandComplete procedure} testbytestring {
    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
    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}
} {abc,,def}
test parse-18.16 {Tcl_SubstObj, exception handling} {
    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}
} {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 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 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}
    } 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]







|


|


|





|


|



|







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}
} {abc,,def}
test parse-18.16 {Tcl_SubstObj, exception handling} {
    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}
} {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 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 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}
    } 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
# 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.
#
# 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]]

# 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    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
} {- {} 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 {}}




|
|










|

















|

|









|

|

|





|

|









|

|

|














|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# 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 © 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 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    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\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 {}}
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]]
} -returnCodes error -result [format {invalid character "@"
in expression "...%s" @ 0"} [string repeat \u00a7 10]]
test parseExpr-21.38 {error messages} -body {
    expr [format {0 @ "%s"} [string repeat \u00a7 25]]
} -returnCodes error -result [format {invalid character "@"
in expression "0 @ "%s..."} [string repeat \u00a7 10]]
test parseExpr-21.39 {error messages} -body {
    expr [format {"%s" @ "%s"} [string repeat \u00a7 25] [string repeat \u00a7 25]]
} -returnCodes error -result [format {invalid character "@"
in expression "...%s" @ "%s..."} [string repeat \u00a7 10] [string repeat \u00a7 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
    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]]
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..."}
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







|

|

|

|

|

|









|





|










|
|







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 \xA7 25]]
} -returnCodes error -result [format {invalid character "@"
in expression "...%s" @ 0"} [string repeat \xA7 10]]
test parseExpr-21.38 {error messages} -body {
    expr [format {0 @ "%s"} [string repeat \xA7 25]]
} -returnCodes error -result [format {invalid character "@"
in expression "0 @ "%s..."} [string repeat \xA7 10]]
test parseExpr-21.39 {error messages} -body {
    expr [format {"%s" @ "%s"} [string repeat \xA7 25] [string repeat \xA7 25]]
} -returnCodes error -result [format {invalid character "@"
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 \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 \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 {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
    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
    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 {







|







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
    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
} -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
} -returnCodes error -match glob -result {*invalid character*}
test parseExpr-22.20 {Bug d2ffcca163} -constraints testexprparser -body {
    testexprparser \u043f -1
} -returnCodes error -match glob -result {*invalid character*}
test parseExpr-22.21 {Bug d2ffcca163} -constraints testexprparser -body {
    testexprparser in\u0433(0) -1
} -returnCodes error -match glob -result {missing operand*}









# cleanup
cleanupTests
return







|


|


|

>
>
>
>
>
>
>
>




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 г -1
} -returnCodes error -match glob -result {*invalid character*}
test parseExpr-22.20 {Bug d2ffcca163} -constraints testexprparser -body {
    testexprparser п -1
} -returnCodes error -match glob -result {*invalid character*}
test parseExpr-22.21 {Bug d2ffcca163} -constraints testexprparser -body {
    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
# Commands covered:  set (plus basic command syntax).  Also tests the
# procedures in the file tclOldParse.c.  This set of tests is an old
# one that predates the new 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.
#
# 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]]

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








|
|
|










|


<







1
2
3
4
5
6
7
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:  set (plus basic command syntax).  Also tests the
# procedures in the file tclOldParse.c.  This set of tests is an old
# one that predates the new 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 © 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 tcl::test [info patchlevel]]

testConstraint testwordend [llength [info commands testwordend]]


# 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
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}
    set a
} 7.7

# Variable substitution.

test parseOld-5.1 {variable substitution} {
    set a 123







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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}
    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
} "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"]}
} 1
test parseOld-7.13 {backslash substitution} testbytestring {
    expr {[list \u4e21] eq [testbytestring "\xe4\xb8\xa1"]}
} 1
test parseOld-7.14 {backslash substitution} testbytestring {
    expr {[list \u4e2k] eq [testbytestring "\xd3\xa2k"]}
} 1

# Semi-colon.

test parseOld-8.1 {semi-colons} {
    set b 0
    getArgs a;set b 2







|
|

|
|

|
|







259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
} "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} {
    expr {[list \uA2] eq "¢"}
} 1
test parseOld-7.13 {backslash substitution} {
    expr {[list \u4E21] eq "両"}
} 1
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
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
    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
# 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
	#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"







|




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|







450
451
452
453
454
455
456
457
458
459
460
461


































































462
463
464
465
466
467
468
469
470
471
    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}
# skip this!
]"
} {2}



































































test parseOld-15.1 {TclScriptEnd procedure} {
    info complete {puts [
	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
# 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.
#
# 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::*






|
|
|







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 © 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::*

Changes to tests/pkgMkIndex.test.

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.
# All rights reserved.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}








|







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 © 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
#  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]
}
} [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]
}
} [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}}}}}








|












|







311
312
313
314
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}]
}
} [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}]
}
} [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

makeFile {
package provide pkg3 1.0
namespace eval pkg3 {
    namespace export p3-1 p3-2
}
proc pkg3::p3-1 { num } {
    return {[expr $num * 2]}
}
proc pkg3::p3-2 { num } {
    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}}}}}}








|


|







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}]}
}
proc pkg3::p3-2 { num } {
    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

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
#  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 } {







|







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 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
#  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]]
}
proc circ2::c2-2 { num } {
    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







|


|







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]}]
}
proc circ2::c2-2 { num } {
    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

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]]
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
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}}}}"

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 {}}

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







|





|
|














|
|
>






>






|







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 \
	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
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 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 {}"

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

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
# braces) in result
makeFile {
package provide spacename 1.0
proc {a b} {} {}
proc {c d} {} {}
} [file join pkg spacename.tcl]








|







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 (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
# 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
#
# 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 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]]
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}






|





>











|
<







1
2
3
4
5
6
7
8
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 © 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 tcl::test [info patchlevel]]


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
# 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.
#
# 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]
    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} {









|
|
|















|







1
2
3
4
5
6
7
8
9
10
11
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 © 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}]
    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
    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]
	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]
	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]
	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]
    }
    set y 189
    list [tproc 6] $y
} {195 189}
catch {unset _undefined_}
test proc-old-2.5 {local and global variables} {
    proc tproc x {







|







|








|








|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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}]
	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}]
	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}]
	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}]
    }
    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
    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}
    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
    set info {}
    do {global a; trace vdelete a(1) w 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}}
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







|






|

|






|
|
|







133
134
135
136
137
138
139
140
141
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 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 add var a(1) write t1
    set info {}
    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 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
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
	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}}

# 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 {} {







|











|







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 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 {} 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 {} {
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
} 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
    }
    t1 1
} 20

# cleanup
catch {rename t1 ""}
catch {rename foo ""}
::tcltest::cleanupTests
return







|










500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
} 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
    }
    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
# 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.
#
# 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 procbodytest [expr {![catch {package require procbodytest}]}]
testConstraint memory	    [llength [info commands memory]]

catch {namespace delete {*}[namespace children :: test_ns_*]}
catch {rename p ""}
catch {rename {} ""}
catch {unset msg}










|
|








>

|







1
2
3
4
5
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 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 © 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 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}

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
         [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)]
	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} {







|







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
         [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)}]
	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} {
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
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
# 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 {
    proc p x {return "$x:$x"}
    set rv [p P]
    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
    lappend rv [t T]
} -constraints procbodytest -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
    lappend rv [t T]
} -constraints procbodytest -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
    lappend rv [t S T U]
} -constraints procbodytest -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
    lappend rv [t S T U]
} -constraints procbodytest -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
    lappend rv [t S T U]
} -returnCodes error -constraints procbodytest -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
    lappend rv [t S T U]
} -constraints procbodytest -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 {
    set end [getbytes]
    for {set i 0} {$i < 5} {incr i} {
	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
} 1










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







|



|


|











|

|









|

|










|

|










|

|










|

|










|

|













|


|








|
|

>
>
>
>
>
>
>
>
>







207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 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 tcl::test -body {
    proc p x {return "$x:$x"}
    set rv [p 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]
    tcl::procbodytest::proc t x p
    lappend rv [t T]
} -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]
    tcl::procbodytest::proc t {x x1 x2} p
    lappend rv [t T]
} -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]
    tcl::procbodytest::proc t {x x1 z} p
    lappend rv [t S T U]
} -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]
    tcl::procbodytest::proc t {x y z} p
    lappend rv [t S T U]
} -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]
    tcl::procbodytest::proc t {x y {z Z}} p
    lappend rv [t S T U]
} -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]
    tcl::procbodytest::proc t {x y {z ZZ}} p
    lappend rv [t S T U]
} -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 {tcl::test memory} -body {
    set end [getbytes]
    for {set i 0} {$i < 5} {incr i} {
	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} 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

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
} {}









# cleanup
catch {rename p ""}
catch {rename t ""}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:







>
>
>
>
>
>
>












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
# 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
# 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::*
}






|







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 © 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::*
}

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
# 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.
#
# 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
} 1

test pwd-1.3 {pwd takes no args} -body {
    pwd foobar
} -returnCodes error -result "wrong \# args: should be \"pwd\""

# cleanup
::tcltest::cleanupTests
return






|
|
|













|

>
|






1
2
3
4
5
6
7
8
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 © 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}
} 1

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
# 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.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [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










|







|







1
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 © 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 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

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"


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}







|
|







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[\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
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"


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







|
|







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\\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
    # 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





# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>
>
>
>








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
# 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.
#
# 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

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]






|
|
|










|







1
2
3
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 © 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
    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
    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"







|
|







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 "b q"
    regexp "b q" "ab 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
} {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"
} {{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"] \
	[regexp -inline -indices -start 4 {(\w+)-(\w+)} \
	"gr\u00FC\u00DF-\u043F\u0440\u0438\u0432\u0435\u0442"]
} {{{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







|




|

|







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üß-привет"
} {{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üß-привет"] \
	[regexp -inline -indices -start 4 {(\w+)-(\w+)} \
	"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
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
    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







|
|







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 "xyz555ijkabpqr"
    regsub ab xyzabijkabpqr 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
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]
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}







|
|







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]
} -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}

Changes to tests/regexpComp.test.

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.
#
# 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::*






|
|
|







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 © 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
} 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
	list [string compare $foo $bar] [regexp 4 $bar]
    }
} {0 0}

test regexpComp-1.8 {regexp ***= metasyntax} {
    evalInProc {
	regexp -- "***=o" "aeiou"







|
|







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 "b q"
	regexp "b q" "ab qw幎N wq" bar
	list [string compare $foo $bar] [regexp 4 $bar]
    }
} {0 0}

test regexpComp-1.8 {regexp ***= metasyntax} {
    evalInProc {
	regexp -- "***=o" "aeiou"
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
	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







|
|







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 "xyz555ijkabpqr"
	regsub ab xyzabijkabpqr 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
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 abcdefghijklmnopqurstuvwxyz0123456789 37 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} {







|

|







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]
    }
} [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} {

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
# 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.

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]
	}]} {
	testConstraint reg 1
    }
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]

# 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}
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} {









|
|










|




|









|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 © 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.7]
	}]} {
	testConstraint reg 1
    }
}
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]

# determine the current locale
testConstraint english [expr {
    [llength [info commands testlocale]]
    && [string match "English*" [testlocale all ""]]
}]

test registry-1.0 {check if we are testing the right dll} {win reg} {
    set ::regver
} {1.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} {

Changes to tests/remote.tcl.

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.
#
# 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 command array
catch {unset command}
set command(0) ""
set callerSocket ""

# Detect whether we should print out connection messages etc.






|




|







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 © 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 delimiter

# Initialize command array
catch {unset command}
set command(0) ""
set callerSocket ""

# Detect whether we should print out connection messages etc.
87
88
89
90
91
92
93
94
95
96
97
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]]
	    }
	    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]]
	    }
	    break
	}
    }
}
if {![info exists serverAddress]} {
    set serverAddress 0.0.0.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
    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 < $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 < $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
# 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.
#
# 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]]

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}






|
|
|










|







1
2
3
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 © 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 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}

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
# 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 <[email protected]>
# Copyright (c) 2011 Stefan Sobernig <[email protected]>
#
# 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]]

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 }






|
|










|







1
2
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 © 2011 Gustaf Neumann <[email protected]>
# Copyright © 2011 Stefan Sobernig <[email protected]>
#
# 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 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
# 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
# interpreter per test-case.
#
#
# Testing resolver in namespace-based context "ctx1"
#
test resolver-3.1a {
    interp command resolver,







|







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
# 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
# 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.
#
# 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]]

# 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]]






|
|










|







1
2
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 © 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 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
    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 {}
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 {}
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]
        }







|






|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
    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
}  -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 {}
} -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]
        }

Changes to tests/safe-stock.test.

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.
#
# 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::*







|
|







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 © 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::*
93
94
95
96
97
98
99
100
101
102
103


104
105





106
107
108
109
110
111
112
113
114
115
116



117
118







119
120
121
122
123
124
125
126
127
128
129
130
131
132



133
134
135







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150



151
152
























153
154
155
156
157
158
159
160
161
162
163
164





165
166
167
168
169
170
171
    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}



# high level general test
test safe-stock-7.1 {tests that everything works at high level, uses pkg opt} -setup {





    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



} -match glob -result 0.4.*
test safe-stock-7.2 {tests specific path and interpFind/AddToAccessPath, uses pkg opt} -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"]
    # 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 {



} -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 {







} -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]
    # 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 0.4.* --\
        {TCLLIB * TCLLIB/OPTDIR} -- {}}

























# 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 {





} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $tcl_library $pkgOptDir] \
                                            [file join $tcl_library $pkgJarDir]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]







|
|


>
>

|
>
>
>
>
>











>
>
>

|
>
>
>
>
>
>
>














>
>
>


|
>
>
>
>
>
>
>















>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|
>
>
>
>
>







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
    set listOut {}
    foreach element $listIn {
        lappend listOut [string map $map $element]
    }
    lsort $listOut
}

# 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 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 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 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]
    # 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} -- {}}
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 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]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
192
193
194
195
196
197
198



199
200
201
202
203





204
205
206
207
208
209
210
    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
} -cleanup {
    safe::interpDelete $i



} -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 {





} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library \
                                            [file join $tcl_library $pkgOptDir] \
                                            [file join $tcl_library $pkgJarDir]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]







>
>
>




|
>
>
>
>
>







251
252
253
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 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
} -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 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]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
227
228
229
230
231
232
233



234
235
236






























































































































237
238
239
240
241
242
243
244
245
246
247
248
    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
} -cleanup {
    safe::interpDelete $i



} -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*}}































































































































set ::auto_path $SaveAutoPath
unset pkgOptErrMsg pkgOptDir pkgJarDir SaveAutoPath TestsDir PathMapp
rename mapList {}
rename mapAndSortList {}
# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












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 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
} -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*}}

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
# 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.
#
# 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-




if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

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 ZipMountPoint [zipfs root]auto-files
zipfs mount $ZipMountPoint [file join $TestsDir auto-files.zip]

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
}

# 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 TcltestPackage [expr {![catch {package require Tcltest}]}]

# 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] \
                        [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}

# 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)
    list $token1 $token2 $token3 -- \
            [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg -- \
            $mappA -- [safe::interpDelete $i]
} -cleanup {



} -match glob -result {{$p(:0:)} {$p(:*:)} {$p(:*:)} --\
        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
    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 {



} -match glob -result {{$p(:0:)} {$p(:*:)} -- 0 1.2.3 --\
        {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 \
                                            [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]]

    # 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 $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]]

    # 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 --\
        {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 \
                                            [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]]

    # 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 $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]]

    # 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:)} --\
        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 \
                                            [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]]

    # 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 $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]]

    # 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
} -cleanup {
    safe::interpDelete $i



} -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}
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 \
                                            [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]]

    # 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 $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]]

    # 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
} -cleanup {
    safe::interpDelete $i



} -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}
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 \
                                            [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]]

    # 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]

    # 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]

    list $path1 $path2 -- $code4 $path4 -- $code5 $path5 -- $code3 $code6 -- \
            $mappA -- $mappB
} -cleanup {
    safe::interpDelete $i



} -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*}}
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]]

    # 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}]

    list [lsort [list $path0 $path1 $path2]] -- $modsA -- \
            $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:)}} --\
        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]]

    # 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]]

    # 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 $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.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]]

    # 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



} -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.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]]

    # 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]]

    # 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]]

    # 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.














# cleanup
set ::auto_path $SaveAutoPath
zipfs unmount ${ZipMountPoint}
unset SaveAutoPath TestsDir ZipMountPoint PathMapp
rename mapList {}
rename mapAndSortList {}
::tcltest::cleanupTests
return


# Local Variables:
# mode: tcl
# End:









|
|




<

>
>
>
|
|
|
|

|
|
|

|
|
|

|
|

|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|

<
<
|
<

|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|
|
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
|
>
>
>
|
<
<
|
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
<
|
<
|
|
|
>
>
>
|
<

|
>
>
>
>
>
|
|
<
<
|
|
|
|
|

|
|

|
|
|
|

|
|
<
<
|
|
|
|
|

|
|
|

|
|
|
>
>
>
|
<
<
|
>
>
>
>
>
|
|
<
<
|
|
|
|
|

|
|

|
|

|
|
<
<
|
|
|
|
|

|
|
|

|
|
|
>
>
>
|
<
<
<
|
>
>
>
>
>
|
|
|
<
<
<
|
|
|
|
|
|

|
|

|
|
|
|
<
<
<
|
|
|
|
|

|
|
|
|
|

|
<
|
|
>
>
>
|
<
<
<
|
>
>
>
>
>
|
|
<
<
|
|
|
|
|

|
|

|
|
<
<
|
|
|
|
|

|
|
|
|
|

|
<
|
|
>
>
>
|
<
<
<
<
|
>
>
>
>
>
|
|
<
<
|
|
|
|
|

|
|

|
|

|
|
|
|
|

|
|
|

|
<
|
|
>
>
>
|
<
<
|
>
>
>
>
>
|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
<
|
|
|
|
|
|
>
>
>
|
<
<
<
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
<
<
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|
|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
>
>
>
|
<
<
<
<
<
<
<
|
|
>
>
>
>
>
|
|
|
|
|
|
|

|
|
|
|
|
|
|

>
>
>
>
>
|
|
|
<
<
|
|
|
|
|
|
|
>
>
>
>
>

|
|
|
|
|
|
|

|
<
<
<
|
|
|
|
|
|
>
>
>
|
<
<
<
<
<
<
<
|
|
>
>
>
>
>
|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|

|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
<
<
<
|
|
|
|
|
|
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
|
|
|
|
|
|
>




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57


58

59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215

216

217
218
219
220
221


222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239

240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255


256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271


272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288


289
290
291
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 © 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.



apply [list {} {
    global auto_path
    global tcl_library
    if {"::tcltest" ni [namespace children]} {
        package require tcltest 2.5
        namespace import -force ::tcltest::*
    }

    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 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

    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}



    testConstraint AutoSyncDefined 1


    # 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]  [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}

    # 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 --  $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 ZIPDIR/auto0} -- {}}


    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 --  $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 * ZIPDIR/auto0/auto1} -- {}}


    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]]]


        # 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 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 $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]]

        # 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 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) 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]]]


        # 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}

        # 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 $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]]

        # 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 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 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]]]



        # 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}}

        # 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]]



        # 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]

        list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 --  $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 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 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]]]


        # 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}}

        # 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]]


        # 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]

        list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 --  $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 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, 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]]]


        # 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}}

        # 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]

        # 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

    } -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*}}


    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]]

        # 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 $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}



    # - 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]]

        # 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]]

        # 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 $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}







    # 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]]

        # 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]]

        # 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
        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.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]]

        # 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]]

        # 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}
    # 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
} [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
# 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
#   - 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.
#
# 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::*
}



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 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}

# 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 TcltestPackage [expr {![catch {package require Tcltest}]}]




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 {








    safe::interpCreate -help




} -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.3 {safe::interpInit syntax} -returnCodes error -body {
    safe::interpInit -noStatics
} -result {bad value "-noStatics" for parameter
    child name () name of the child}



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}










|





|
|








>
>










>
>
>
>
>















|
|



|

|
>

>
>




|
>
>
>
>
>
>
>
>

>
>
>
>











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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 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 © 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]
    }
    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 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 - tcl::test - but it might be absent if we're in standard tclsh)

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, 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
} -body {
    interp create a -safe
    lsort [a aliases]
} -cleanup {
    interp delete a
} -result {clock}




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 {







>
>
>







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
} -body {
    safe::interpCreate a
    interp eval a {source [file join $tcl_library init.tcl]}
} -cleanup {
    safe::interpDelete a
} -result {}



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.







>
>







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
test safe-4.6 {safe::interpDelete, indirectly} -setup {
    catch {safe::interpDelete a}
} -body {
    safe::interpCreate a
    a eval exit
} -result ""


# 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.


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]







>
|
|
|
>







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".

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]
278
279
280
281
282
283
284
285

286
287
288
289
290
291
292
    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'

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







|
>







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}

###  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
    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 {






    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



} -match glob -result 1.2.3
test safe-7.2 {tests specific path and interpFind/AddToAccessPath} -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 $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
    # provided deep path)
    list $token1 $token2 $token3 -- \
	    [catch {interp eval $i {package require SafeTestPackage1}} msg] $msg -- \
	    $mappA -- [safe::interpDelete $i]
} -cleanup {



} -match glob -result {{$p(:0:)} {$p(:*:)} {$p(:*:)} --\
        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}







|
|
>
|
>
>
>
>
>
>














>
>
>

|
>
>
>
>
>
>
>










|
<




>
>
>







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
    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...

###  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 {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 in auto0 but a subdirectory)

    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} -- {}}
test safe-7.3 {check that safe subinterpreters work} {
    set g [interp children]
    if {$g ne {}} {
        append g { -- residue of an earlier test}
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
    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*]
} -match glob -result {{} {} ok ok {} 0 {}}
test safe-7.4 {tests specific path and positive search} -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 $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 {



} -match glob -result {{$p(:0:)} {$p(:*:)} -- 0 1.2.3 --\
        {TCLLIB * TESTSDIR/auto0/auto1} -- {}}


























# 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 {







|
>
>
>
>
>
>
>















>
>
>


>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>







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
    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*]
} -match glob -result {{} {} ok ok {} 0 {}}
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 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
    }} $token/[file tail $returnScript]]
} -cleanup {
    catch {safe::interpDelete $i}
    removeFile $returnScript
    unset i
} -result ok




test safe-9.1 {safe interps' deleteHook} -setup {
    set i "a"
    catch {safe::interpDelete $i}
    set res {}
} -body {
    proc testDelHook {args} {
	global res







>
>
>







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
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
	[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}}
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







|
|
|
|







730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
	[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} -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
	   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 {





} -body {
    set i [safe::interpCreate -accessPath [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]]

    # 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



} -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 {





} -body {
    set i [safe::interpCreate -accessPath [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]]







|
|
|
|
|
>
>
>
>
>

















>
>
>


|
>
>
>
>
>







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
	   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} -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]]]
    # 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), 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]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
699
700
701
702
703
704
705



706
707
708
709





710
711
712
713
714
715
716
    # 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 --\
        {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 {





} -body {
    set i [safe::interpCreate -accessPath [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]]







>
>
>



|
>
>
>
>
>







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
    # 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), 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]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
736
737
738
739
740
741
742



743
744
745
746
747





748
749
750
751
752
753
754
    # 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:)} --\
        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 {





} -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]]]
    # Inspect.







>
>
>




|
>
>
>
>
>







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
    # 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, 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]]]
    # Inspect.
780
781
782
783
784
785
786



787
788
789
790
791





792
793
794
795
796
797
798
    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
} -cleanup {
    safe::interpDelete $i



} -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 {





} -body {
    set i [safe::interpCreate -accessPath [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]]







>
>
>




|
>
>
>
>
>







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
    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
} -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, 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]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
819
820
821
822
823
824
825



826
827
828
829
830
831





832
833
834
835
836
837
838
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
            $mappA -- $mappB -- \
            $code5 $msg5 $code6 $msg6
} -cleanup {
    safe::interpDelete $i



} -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 {





} -body {
    set i [safe::interpCreate -accessPath [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]]







>
>
>





|
>
>
>
>
>







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
    set code6 [catch {interp eval $i {HeresPackage2}} msg6 opts6]

    list $path1 $path2 -- $path3 $path4 -- $code3 $msg3 $code4 $msg4 -- \
            $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, 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]]]
    # Inspect.
    set confA [safe::interpConfigure $i]
    set mappA [mapList $PathMapp [dict get $confA -accessPath]]
855
856
857
858
859
860
861



862
863
864
865





866
867
868
869
870
871
872
    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
} -cleanup {
    safe::interpDelete $i



} -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 {





    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]]







>
>
>



|
>
>
>
>
>







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
    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
} -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, 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 add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]
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
            $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



} -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}
# - 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 {





    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]]







>
>
>













|
>
>
>
>
>







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
            $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}
# - 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, 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 add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]
957
958
959
960
961
962
963



964
965
966
967
968
969
970
971
972
973





974
975
976
977
978
979
980
            $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



} -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-9.22 {interpConfigure change the access path; check module loading; stale data case 0} -setup {





    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]]







>
>
>









|
>
>
>
>
>







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
            $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-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 add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]
1014
1015
1016
1017
1018
1019
1020



1021
1022
1023
1024
1025
1026
1027
1028
1029
1030





1031
1032
1033
1034
1035
1036
1037
            $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



} -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-9.23 {interpConfigure change the access path; check module loading; stale data case 3} -setup {





    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]]







>
>
>









|
>
>
>
>
>







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
            $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-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 add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]
1081
1082
1083
1084
1085
1086
1087



1088
1089
1090
1091
1092
1093
1094
1095
1096
1097





1098
1099
1100
1101
1102
1103
1104
            $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



} -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-9.24 {interpConfigure change the access path; check module loading; stale data case 2 (worst case)} -setup {





    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]]







>
>
>









|
>
>
>
>
>







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
            $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-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 add [file join $TestsDir auto0 modules]
} -body {
    set i [safe::interpCreate -accessPath [list $tcl_library]]
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
            $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



} -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.



catch {teststaticpkg Safepkg1 0 0}
test safe-10.1 {testing statics loading} -constraints TcltestPackage -setup {
    set i [safe::interpCreate]
} -body {
    interp eval $i {load {} Safepkg1}
} -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 {
    set i [safe::interpCreate]
} -body {
    catch {interp eval $i {load {} Safepkg1}} m o
    dict get $o -errorinfo
} -returnCodes ok -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
    invoked from within
"load {} Safepkg1"
    invoked from within
"interp eval $i {load {} Safepkg1}"}
test safe-10.2 {testing statics loading / -nostatics} -constraints TcltestPackage -body {
    set i [safe::interpCreate -nostatics]
    interp eval $i {load {} Safepkg1}
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {permission denied (static package)}
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}
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {permission denied (nested load)}
test safe-10.4 {testing nested statics loading / -nestedloadok} -constraints TcltestPackage -body {
    set i [safe::interpCreate -nestedloadok]
    interp eval $i {interp create x; load {} Safepkg1 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 {
    set i [safe::interpCreate -nestedloadok]
    catch {interp eval $i {interp create x; load {} Safepkg1 x}} m o
    dict get $o -errorinfo
} -returnCodes ok -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
    invoked from within
"load {} Safepkg1 x"
    invoked from within
"interp eval $i {interp create x; load {} Safepkg1 x}"}



test safe-11.1 {testing safe encoding} -setup {
    set i [safe::interpCreate]
} -body {
    interp eval $i encoding
} -returnCodes error -cleanup {
    safe::interpDelete $i







>
>
>










>
>
|
|


|


|
|


|

|


|

|

|
|

|


|


|
|



|

|


|
|

|

|


|

|

|
>
>







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
            $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.

### 10. Test options -statics -nostatics -nested -nestedloadok

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 {} Safepfx1}
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {load of library for prefix Safepfx1 failed: can't 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 {} Safepfx1}} m o
    dict get $o -errorinfo
} -cleanup {
    unset -nocomplain m o
    safe::interpDelete $i
} -result {load of library for prefix Safepfx1 failed: can't use library in a safe interpreter: no Safepfx1_SafeInit procedure
    invoked from within
"load {} Safepfx1"
    invoked from within
"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 {} Safepfx1}
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {permission denied (static library)}
test safe-10.3 {testing nested statics loading / no nested by default} -setup {
    set i [safe::interpCreate]
} -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 tcl::test -body {
    set i [safe::interpCreate -nestedloadok]
    interp eval $i {interp create x; load {} Safepfx1 x}
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {load of library for prefix Safepfx1 failed: can't 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 {} Safepfx1 x}} m o
    dict get $o -errorinfo
} -cleanup {
    unset -nocomplain m o
    safe::interpDelete $i
} -result {load of library for prefix Safepfx1 failed: can't use library in a safe interpreter: no Safepfx1_SafeInit procedure
    invoked from within
"load {} Safepfx1 x"
    invoked from within
"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
} -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"}
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 {
    unset -nocomplain m o
    safe::interpDelete $i
} -result {wrong # args: should be "encoding convertfrom ?encoding? 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"}
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 {
    unset -nocomplain m o
    safe::interpDelete $i
} -result {wrong # args: should be "encoding convertto ?encoding? data"
    while executing
"encoding convertto"
    invoked from within
"encoding convertto"
    invoked from within
"interp eval $i encoding convertto"}




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"







|





|


|












|





|


|







>
>
>







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 ?-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
} -match glob -cleanup {
    unset -nocomplain m o
    safe::interpDelete $i
} -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 ?-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
} -match glob -cleanup {
    unset -nocomplain m o
    safe::interpDelete $i
} -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
    set i [safe::interpCreate]
} -body {
    $i eval glob *
} -returnCodes error -cleanup {
    safe::interpDelete $i
} -result {permission denied}




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}







>
>
>















|







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
    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]
}

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}
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
} -cleanup {
    safe::interpDelete $i
    removeDirectory $testdir
} -result {}
rename buildEnvironment {}
rename buildEnvironment2 {}


#### 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]
    }
    return $tm
} -cleanup {
    safe::interpDelete $i
} -result [::tcl::tm::path list]





















































































































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 .}}]







>
|











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
} -cleanup {
    safe::interpDelete $i
    removeDirectory $testdir
} -result {}
rename buildEnvironment {}
rename buildEnvironment2 {}

### 14. Sanity checks on paths - module path, access path, auto_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]
    }
    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
    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



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]







|
>
>
>







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 .}"}}

### 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
	set d [format %c 126]
	file join {$p(:0:)} $d
    }
} -cleanup {
    safe::interpDelete $i
    set env(HOME) $savedHOME
    unset savedHOME
} -result {~}
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 {~}
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}
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 {~USER}





















































































































































































































































































































































































# cleanup
set ::auto_path $SaveAutoPath
unset SaveAutoPath TestsDir PathMapp


rename mapList {}
rename mapAndSortList {}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|













|








|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




>
>








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 {$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 {$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 {$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 {{} -- {}}
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
# 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.
#
# 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::*






|
|
|







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 © 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

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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}







|

|









|

|

|





|

|









|

|

|







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 0
	}
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
} -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
# 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}]







|







504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
} -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 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}]
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
    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 {
    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 {}







|







601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
    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.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
    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"
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
} -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"

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 ...?"}







|
|



|




|
|







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
    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Ç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Ç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"

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
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}







# scan infinities - not working

test scan-14.1 {positive infinity} {
    scan Inf %g d
    return $d
} Inf







>
>
>
>
>
>







854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
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
# 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.
# All rights reserved.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}









|
|







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 © 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
# 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.
#
# 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::*








|
|
|







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 © 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
    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
    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}}







|







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 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}}
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
    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
    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







|







403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
    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 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
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
    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
    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
    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







|





|







441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
    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 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 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
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
    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
    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]
        }







|







575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
    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 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]
        }
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 {}
    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 {}
    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 {}
    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"}}







|








|






|







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 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 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 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
# 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.
#
# 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]]

testConstraint testset2 [llength [info commands testset2]]

catch {unset x}
catch {unset i}

test set-1.1 {TclCompileSetCmd: missing variable name} {






|
|










|







1
2
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 © 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]]

testConstraint testset2 [llength [info commands testset2]]

catch {unset x}
catch {unset i}

test set-1.1 {TclCompileSetCmd: missing variable name} {
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
    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







|







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 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
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
    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







|







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 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
# 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.
#
# 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:
# ------------------------------------------
#






|
|







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 © 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

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
::tcltest::loadTestedCommands



if {[expr {[info exists ::env(TRAVIS_OSX_IMAGE)] && [string match xcode* $::env(TRAVIS_OSX_IMAGE)]}]} {
    return
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]

# 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 knownMsvcBug [expr {![info exists ::env(TRAVIS_OS_NAME)] || ![string match windows $::env(TRAVIS_OS_NAME)]}]

# 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 {







|


>
>
|


|




>
|







62
63
64
65
66
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 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 {[info exists ::env(MAC_CI)]} {
    return
}
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 {
     $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 {
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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
# 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}]








|







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 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}]

291
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
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"}]



# ----------------------------------------------------------------------

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"}
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"}
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"}
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}
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"}
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"}
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}
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}
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}
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}
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 {







>
>








|





|








|


|





|


|











|


|





|


|







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
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 ?-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 ?-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 ?-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, -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 ?-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 ?-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 -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 -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 -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 -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 {
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

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 {couldn't open socket: not owner}
} -constraints [list socket supported_$af unix notRoot notOSX] -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}

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}
    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







|













|

















|







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

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 {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 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}}
    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
} -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
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







|







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 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
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
  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):
      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
      }
    }
    tcltest::DebugPuts 1 "== 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
    ]







|







|







1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
  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 (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
      }
    }
    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
    ]
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
          }} $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:
    proc transf_parent {fd args} {
      tcltest::DebugPuts 1 "** trma / $::count ** $args **"
      thread::attach $fd
      if {"parent-close" in $::testmode} {;# to test close during connect
        set ::count $::count
        close $fd
        return
      };#
      fileevent $fd writable [list apply {{fd} {







|

|







1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
          }} $fd]
        };#
        thread::detach $fd
        thread::send -async $::parent [list transf_parent $fd {*}$args]
      }
      iteration first
    }
    # parent proc committing transfer attempt (attach) and checking acquire was successful:
    proc transf_parent {fd 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
      };#
      fileevent $fd writable [list apply {{fd} {
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
      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 {[incr ::count] >= $maxIter} break
      tcltest::DebugPuts 1 "** 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 =="
    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 {







|








|







1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
      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 {[incr ::count] >= $maxIter} break
      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 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 {
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
    -constraints {socket} \
    -body {
        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} {}}
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}







|







2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
    -constraints {socket} \
    -body {
        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*": 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}
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
        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} {}}
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}







|







2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
        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*": 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}
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
        list [fconfigure $sock -error] [gets $fd]
    } -cleanup {
        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} \
    -body {
        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
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
    } -cleanup {
        catch {close $sock}
        catch {unset x}
    } -result {socket 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







|










|


















|







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
        list [fconfigure $sock -error] [gets $fd]
    } -cleanup {
        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 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
    } -cleanup {
        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
    } -cleanup {
        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
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452

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

    # 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







|







2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457

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

    # 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
2571
2572
2573
2574
2575
2576
2577








2578
2579
2580
2581
2582
2583
2584
2585
2586
            } -cleanup {
                close $server
                catch {close $s}
            } {*}$result
        incr num
    }
}









::tcltest::cleanupTests
flush stdout
return

# Local Variables:
# mode: tcl
# fill-column: 78
# End:







>
>
>
>
>
>
>
>









2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
            } -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
# 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.
# 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."






|
|
|







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 © 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."
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"
    close $out
    set y old-y
    source $sourcefile
    return $y
} -cleanup {
    removeFile $sourcefile
} -result {new-y}







|







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"
    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
} -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]
} -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]
} -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"
    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
    # EOF character by [source].  Here we write out and the [source] a
    # file that contains the byte \x1A, although not the character \u001A 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"
    close $f
} -body {
    set x unset
    source -encoding utf-16 $sourcefile
    set x
} -cleanup {
    removeFile source.file







|








|













|










|

|





|







195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
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\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\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) ; 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 (\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 \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) ; 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
    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}"
    close $f
} -body {
    source $sourcefile
    \u20ac

} -cleanup {
    removeFile source.file
    rename \u20ac {}
} -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}"
    close $f
} -body {
    source -encoding ascii $sourcefile
    \u20ac

} -cleanup {
    removeFile source.file
} -returnCodes error -match glob -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







|



<
>


|






|


|
<
>


|







262
263
264
265
266
267
268
269
270
271
272

273
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  {} {return foo}"
    close $f
} -body {
    source $sourcefile


} -cleanup {
    removeFile source.file
    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  {} {return foo}"
    close $f
} -body {
    source -encoding iso8859-1 $sourcefile


} -cleanup {
    removeFile source.file
} -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
# 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.
#
# 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::*






|
|
|







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 © 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::*
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
        }
        return $x
    }
    foo
} {]\n}
test split-1.9 {basic split commands} {
    proc foo {} {
        set x ab\000c
        set y [split $x {}]
        return $y
    }
    foo
} "a b \000 c"
test split-1.10 {basic split commands} {
    split "a0ab1b2bbb3\000c4" ab\000c
} {{} 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
} {{} 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"
test split-1.16 {basic split commands} -body {
    split "a\U1F4A9b" \U1F4A9
} -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







|




|

|





|








|
|

|







45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
        }
        return $x
    }
    foo
} {]\n}
test split-1.9 {basic split commands} {
    proc foo {} {
        set x ab\x00c
        set y [split $x {}]
        return $y
    }
    foo
} "a b \x00 c"
test split-1.10 {basic split commands} {
    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 "\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💩b" {}
} -result "a 💩 b"
test split-1.16 {basic split commands} -body {
    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
# 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.
#
# 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::*






|







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 © 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
# 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.
#
# 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]]



# 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]






|
|
|
|










|
>
>












<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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:  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 © 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 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 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]
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    set constraints testevalex
} else {
    interp alias {} run {} try
    set constraints {}
}


test string-1.1.$noComp {error conditions} {
    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}}
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} {







|

|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    set constraints testevalex
} else {
    interp alias {} run {} try
    set constraints {}
}


test string-1.1.$noComp {error conditions} -body {
    list [catch {run {string gorp a b}} msg] $msg
} -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} {
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
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}
} -1
test string-2.11.1.$noComp {string compare, unicode} {
    run {string compare \334 \xDC}
} 0
test string-2.11.2.$noComp {string compare, unicode} {
    run {string compare \334 \xFC}
} -1
test string-2.11.3.$noComp {string compare, unicode} {
    run {string compare \334\334\334\374\374 \334\334\334\334\334}
} 1
test string-2.12.$noComp {string compare, high bit} {
    # This test will fail 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}
} 0
test string-2.15.2.$noComp {string compare -nocase} {
    run {string compare -nocase \334\334\334\374\xFC \334\334\334\334\334}
} 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}
} -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







|


|


|


|


|




















|


|
















|







116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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 ab}
} -1
test string-2.11.1.$noComp {string compare, unicode} {
    run {string compare Ü Ü}
} 0
test string-2.11.2.$noComp {string compare, unicode} {
    run {string compare Ü ü}
} -1
test string-2.11.3.$noComp {string compare, unicode} {
    run {string compare ÜÜÜüü ÜÜÜÜÜ}
} 1
test string-2.12.$noComp {string compare, high bit} {
    # 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 Ü Ü}
} 0
test string-2.15.2.$noComp {string compare -nocase} {
    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 ÜÜÜ ÜÜü}
} -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
} 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} {
    run {string compare -length 2 abc abde}
} 0
test string-2.29.$noComp {string compare with length, unequal strings} {
    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







|


|







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, partial first string} {
    run {string compare -length 2 abc abde}
} 0
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
} 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
































# 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}
} 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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
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 ÜÜÜÜüüüü ÜÜÜÜÜÜÜÜ}
} 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
    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}
} 0
test string-3.17.$noComp {string equal, unicode} {
    run {string equal \334 \xDC}
} 1
test string-3.18.$noComp {string equal, unicode} {
    run {string equal \334 \xFC}
} 0
test string-3.19.$noComp {string equal, unicode} {
    run {string equal \334\334\334\374\374 \334\334\334\334\334}
} 0
test string-3.20.$noComp {string equal, high bit} {
    # This test will fail if the underlying comparaison
    # 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}
} 1
test string-3.23.$noComp {string equal, -nocase unicode} {
    run {string equal -nocase \334\334\334\374\xFC \334\334\334\334\334}
} 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}
} 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







|


|


|


|


|











|


|
















|







302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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 ab}
} 0
test string-3.17.$noComp {string equal, unicode} {
    run {string equal Ü Ü}
} 1
test string-3.18.$noComp {string equal, unicode} {
    run {string equal Ü ü}
} 0
test string-3.19.$noComp {string equal, unicode} {
    run {string equal ÜÜÜüü ÜÜÜÜÜ}
} 0
test string-3.20.$noComp {string equal, high bit} {
    # 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 Ü Ü}
} 1
test string-3.23.$noComp {string equal, -nocase unicode} {
    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 ÜÜÜ ÜÜü}
} 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
} 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-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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
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}
} 4
test string-4.10.$noComp {string first, unicode} {
    run {string first \u7266 abc\u7266x}
} 3
test string-4.11.$noComp {string first, start index} {
    run {string first \u7266 abc\u7266x 3}
} 3
test string-4.12.$noComp {string first, start index} -body {
    run {string first \u7266 abc\u7266x 4}
} -result -1
test string-4.13.$noComp {string first, start index} -body {
    run {string first \u7266 abc\u7266x 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
    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}
test string-4.18.$noComp {string first, corner case} -body {
    run {string first a aaa -1}
} -result {0}
test string-4.19.$noComp {string first, corner case} -body {
    run {string first a aaa end-5}
} -result {0}
test string-4.20.$noComp {string last, corner case} -body {
    run {string last a aaa 4294967295}
} -result {2}
test string-4.21.$noComp {string last, corner case} -body {
    run {string last a aaa -1}
} -result {-1}
test string-4.22.$noComp {string last, corner case} {
    run {string last a aaa end-5}
} {-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"}}







|


|


|


|


|








|











|


|


|


|


|


|







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 abcx}
} 4
test string-4.10.$noComp {string first, unicode} {
    run {string first  abcx}
} 3
test string-4.11.$noComp {string first, start index} {
    run {string first  abcx 3}
} 3
test string-4.12.$noComp {string first, start index} -body {
    run {string first  abcx 4}
} -result -1
test string-4.13.$noComp {string first, start index} -body {
    run {string first  abcx 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 վ    ;# 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
test string-4.18.$noComp {string first, corner case} -body {
    run {string first a aaa -1}
} -result 0
test string-4.19.$noComp {string first, corner case} -body {
    run {string first a aaa end-5}
} -result 0
test string-4.20.$noComp {string last, corner case} -body {
    run {string last a aaa 4294967295}
} -result 2
test string-4.21.$noComp {string last, corner case} -body {
    run {string last a aaa -1}
} -result -1
test string-4.22.$noComp {string last, corner case} {
    run {string last a aaa end-5}
} -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
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}
} d
test string-5.11.$noComp {string index, unicode} {
    run {string index abc\u7266d 3}
} \u7266
test string-5.12.$noComp {string index, unicode over char length, under byte length} -body {
    run {string index \334\374\334\374 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







|


|
|

|







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 abcd 4}
} d
test string-5.11.$noComp {string index, unicode} {
    run {string index abcd 3}
} 
test string-5.12.$noComp {string index, unicode over char length, under byte length} -body {
    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
} 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 {
    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 {
    run {list [string index a\U100000b 1] [string index a\U100000b 2] [string index a\U100000b 3]}
} -result [list \U100000 b {}]


proc largest_int {} {
    # 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"}}







|

|



|


|
|
|
<
<
<
<
<
<
|







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} {
    run {string index [binary format I* {0x50515253 0x52}] -1}
} {}
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]} -body {
    run {list [string index a\U100000b 1] [string index a\U100000b 2] [string index a\U100000b 3]}
} -result [list \U100000 b {}]
test string-5.22.$noComp {string index} -constraints testbytestring -body {
    run {list [scan [string index [testbytestring \xFF] 0] %c var] $var}
} -result {1 255}








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
} 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.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}
} 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}







|







|







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ü}" 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ü}
} 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
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
} {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)]}
} 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







|








|







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Ü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)}]}
} 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
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
} -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
    #







|







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 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
    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)]}
} 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}
} 1
test string-6.56.$noComp {string is integer, false} {
    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}
} 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
} {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}







|

















|


|

















|








|







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)}]}
} 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 +9223372036854775808}
} 1
test string-6.56.$noComp {string is integer, false} {
    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ü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Ü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
    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}
} 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
} {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}
} 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}







|








|





|







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Ü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ü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ü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
    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)]}
} 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
} {0 -1}
test string-6.103.$noComp {string is wideinteger, false} {
    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}







|

















|


|







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)}]}
} 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 +9223372036854775808}] $var
} {0 -1}
test string-6.103.$noComp {string is wideinteger, false} {
    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
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)]}
} 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
} {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}







|




















|







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)}]}
} 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
} {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
} {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}







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}
} 12
test string-7.8.$noComp {string last, unicode} {
    run {string las \u7266 xxxx12\u7266xx345x678}
} 6
test string-7.9.$noComp {string last, stop index} {
    run {string las \u7266 xxxx12\u7266xx345x678}
} 6
test string-7.10.$noComp {string last, unicode} {
    run {string las \u7266 xxxx12\u7266xx345x678}
} 6
test string-7.11.$noComp {string last, start index} {
    run {string last \u7266 abc\u7266x 3}
} 3
test string-7.12.$noComp {string last, start index} {
    run {string last \u7266 abc\u7266x 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}
} -1
test string-7.16.$noComp {string last, start index} {
    run {string last \334a \334ad\334ad 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"}
} 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}
test string-10.5.$noComp {string map} {
    run {string map {a b} a}
} {b}
test string-10.6.$noComp {string map -nocase} {
    run {string map -nocase {a b} Abba}
} {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}
test string-10.12.$noComp {string map, unicode} {
    run {string map [list \374 ue UE \334] "a\374ueUE\000EU"}
} aueue\334\0EU
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
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}
test string-10.16.$noComp {string map, one pair case} {
    run {string map -nocase {ab 4321} aAbCaBaAbAbcAb}
} {a4321C4321a43214321c4321}
test string-10.17.$noComp {string map, one pair case} {
    run {string map {Ab 4321} aAbCaBaAbAbcAb}
} {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} {







>
>
>
>
>
>

<




















|


|


|


|


|


|










|


|


<
<
<
<
<
<
<
<
<
<
<
<
<













|



















|


|


|














|

|
|

|
|





|


|


|







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



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 xxxx12xx345x678}
} 12
test string-7.8.$noComp {string last, unicode} {
    run {string las  xxxx12xx345x678}
} 6
test string-7.9.$noComp {string last, stop index} {
    run {string las  xxxx12xx345x678}
} 6
test string-7.10.$noComp {string last, unicode} {
    run {string las  xxxx12xx345x678}
} 6
test string-7.11.$noComp {string last, start index} {
    run {string last  abcx 3}
} 3
test string-7.12.$noComp {string last, start index} {
    run {string last  abcx 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 Üa ÜadÜad 0}
} -1
test string-7.16.$noComp {string last, start index} {
    run {string last Üa ÜadÜad end-1}
} 3














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"}
} 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
test string-10.5.$noComp {string map} {
    run {string map {a b} a}
} b
test string-10.6.$noComp {string map -nocase} {
    run {string map -nocase {a b} Abba}
} 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
test string-10.12.$noComp {string map, unicode} {
    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 ü 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
test string-10.16.$noComp {string map, one pair case} {
    run {string map -nocase {ab 4321} aAbCaBaAbAbcAb}
} a4321C4321a43214321c4321
test string-10.17.$noComp {string map, one pair case} {
    run {string map {Ab 4321} aAbCaBaAbAbcAb}
} 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
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}
} 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]} _}







|







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Ü 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]} _}
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
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}
} e
test string-12.18.$noComp {string range, unicode} {
    run {string range ab\u7266cdefghijklmnop 2 3}
} \u7266c
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} {







|


|
|







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 abcdefghijklmnop 5 5}
} e
test string-12.18.$noComp {string range, unicode} {
    run {string range abcdefghijklmnop 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
    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 {
    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
    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]} {
    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
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
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

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}
test string-14.7.$noComp {string replace} {
    run {string replace abcdefghijklmnop 10 end}
} {abcdefghij}
test string-14.8.$noComp {string replace} {
    run {string replace abcdefghijklmnop 10 9}
} {abcdefghijklmnop}
test string-14.9.$noComp {string replace} {
    run {string replace abcdefghijklmnop -3 2}
} {defghijklmnop}
test string-14.10.$noComp {string replace} {
    run {string replace abcdefghijklmnop -3 -2}
} {abcdefghijklmnop}
test string-14.11.$noComp {string replace} -body {
    run {string replace abcdefghijklmnop 1000 1010}
} -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} {







|
|





|
|

















|


|


|


|


|


|







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 abcd 3}
} abcdabcdabcd
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 abcd 2 3}] 3}
} ccc

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
test string-14.7.$noComp {string replace} {
    run {string replace abcdefghijklmnop 10 end}
} abcdefghij
test string-14.8.$noComp {string replace} {
    run {string replace abcdefghijklmnop 10 9}
} abcdefghijklmnop
test string-14.9.$noComp {string replace} {
    run {string replace abcdefghijklmnop -3 2}
} defghijklmnop
test string-14.10.$noComp {string replace} {
    run {string replace abcdefghijklmnop -3 -2}
} abcdefghijklmnop
test string-14.11.$noComp {string replace} -body {
    run {string replace abcdefghijklmnop 1000 1010}
} -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
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 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]]]







>
>
>
>
>
>
>
>
>
>
>
>







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
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]]]
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
} "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 {
    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?"}}







|







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]} {
    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
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} {
    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}}
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} {
    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} {
    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}]]
} [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







|

|












|












|












|







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} -body {
    list [catch {run {string trimg a}} msg] $msg
} -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 {
    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 {
    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 \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
} -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 {
    run {string wordend "\U1D7CA\U1D7CA abc" 10}
} -result 6




























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}}
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 {







|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|







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} -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 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
    # 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 {
    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}







|







2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
    # 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} -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}
2066
2067
2068
2069
2070
2071
2072


















2073
2074
2075
2076
2077
2078
2079
    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-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
    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
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
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"}
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"}
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}







|



|







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 {*, 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 {*, 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}

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
# 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.
#
# 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]]

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




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}








|
|










|




<







>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 © 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 tcl::test [info patchlevel]]

testConstraint testobj [llength [info commands testobj]]
testConstraint testbytestring [llength [info commands testbytestring]]
testConstraint testdstring [llength [info commands testdstring]]


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
    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}
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 {
    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 {







|
|






|
|







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
    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 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
    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}

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}







|







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 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
    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}
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}
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 {
    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}}
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 {}}







|

















|



















|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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 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 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 {
    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 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
    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}
test stringObj-8.2 {DupUnicodeInternalRep, mixed width chars} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    string length $x
    set y $x
    list [testobj objtype $x] [testobj objtype $y] [append x "\u00ae\u00bf\u00ef"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string string abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef abc\u00ef\u00bf\u00aeghi string string"
test stringObj-8.3 {DupUnicodeInternalRep, mixed width chars} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    set y $x
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x "\u00ae\u00bf\u00ef"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "string string abc\u00ef\u00bf\u00aeghi\u00ae\u00bf\u00ef abc\u00ef\u00bf\u00aeghi 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
    testdstring free
    testdstring append \u00ae\u00bf\u00ef -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"
test stringObj-9.2 {TclAppendObjToObj, mixed src & dest} testobj {
    set x abc\u00ef\u00bf\u00aeghi
    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"
test stringObj-9.3 {TclAppendObjToObj, mixed src & 1-byte dest} {testobj testdstring} {
    set x abcdefghi
    testdstring free
    testdstring append \u00ae\u00bf\u00ef -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"
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
    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"
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 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"
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.
    set x abcdef
    set len [string length $x]
    set y a\u00fcb\u00e5c\u00ef
    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"

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
    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]
test stringObj-10.3 {Tcl_GetRange with some mixed width chars} testobj {
    # 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]
test stringObj-10.4 {Tcl_GetRange with some mixed width chars} testobj {
    # 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				\
	{}]

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}







|

|


|

|

|


|

|
















|

|




|

|



|
|




|




|

















|






|




















|




|



|


|








|









<
<
<
<
<

|



|

|
<
<
<



|

|
<
<
<






|
|
|
|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 8 0 abcde 5 5 0 abcde}
test stringObj-8.2 {DupUnicodeInternalRep, mixed width chars} testobj {
    set x abc\xEF\xBF\xAEghi
    string length $x
    set y $x
    list [testobj objtype $x] [testobj objtype $y] [append x "\xAE\xBF\xEF"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "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\xEF\xBF\xAEghi
    set y $x
    string length $x
    list [testobj objtype $x] [testobj objtype $y] [append x "\xAE\xBF\xEF"] \
	    [set y] [testobj objtype $x] [testobj objtype $y]
} "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\xEF\xBF\xAEghi
    testdstring free
    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\xEF\xBF\xAEghi\xAE\xBF\xEF \xAE\xBF\xEF string none"
test stringObj-9.2 {TclAppendObjToObj, mixed src & dest} testobj {
    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\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 \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\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\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\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\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\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.
    set x abcdef
    set len [string length $x]
    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 \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} {





    testdstring free
    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ïïde" string string]
test stringObj-10.3 {Tcl_GetRange with some mixed width chars} testobj {
    set x "abcïïdef"



    string length $x
    list [testobj objtype $x] [set y [string range $x 1 end-1]] \
	    [testobj objtype $x] [testobj objtype $y]
} [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 result [list]
    while {[string length $a] > 0} {
	set a [string range $a 1 end-1]
	lappend result $a
    }
    set result
} [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
    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"
test stringObj-12.5 {Tcl_GetUniChar} testobj {
    set x "\u00efa\u00bfb\u00aec\u00ae\u00bfd\u00ef"
    list [string index $x 4] [string index $x 0]
} "\u00ae \u00ef"
test stringObj-12.6 {Tcl_GetUniChar} testobj {
    string index "\u00efa\u00bfb\u00aec\u00ef\u00bfd\u00ae" end
} "\u00ae"

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"
} 1
test stringObj-13.5 {Tcl_GetCharLength with mixed width chars} testobj {
    # string length "○○"
    # Use \uXXXX notation below instead of hardcoding the values, otherwise
    # the test will fail in multibyte locales.
    string length "\u00EF\u00BF\u00AE\u00EF\u00BF\u00AE"
} 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
    # the test will fail in multibyte locales.
    set a "\u00EFa\u00BFb\u00AEc\u00EF\u00BFd\u00AE"
    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} {







|
|

|

|

|
|













|



|

|



|

|







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 "\xEFa\xBFb\xAEc\xAE\xBFd\xEF" 0
} "\xEF"
test stringObj-12.5 {Tcl_GetUniChar} testobj {
    set x "\xEFa\xBFb\xAEc\xAE\xBFd\xEF"
    list [string index $x 4] [string index $x 0]
} "\xAE \xEF"
test stringObj-12.6 {Tcl_GetUniChar} testobj {
    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 "\xAE"
} 1
test stringObj-13.5 {Tcl_GetCharLength with mixed width chars} testobj {
    # string length "○○"
    # Use \uXXXX notation below instead of hard-coding the values, otherwise
    # the test will fail in multibyte locales.
    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 hard-coding the values, otherwise
    # the test will fail in multibyte locales.
    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
    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} {
    teststringobj set 1 foo
    teststringobj appendself2 1 0
} foofoo
test stringObj-15.6 {Tcl_Append*ToObj: self appends} {testobj fullutf} {
    teststringobj set 1 foo
    teststringobj appendself2 1 1
} foooo
test stringObj-15.7 {Tcl_Append*ToObj: self appends} {testobj fullutf} {
    teststringobj set 1 foo
    teststringobj appendself2 1 2
} fooo
test stringObj-15.8 {Tcl_Append*ToObj: self appends} {testobj fullutf} {
    teststringobj set 1 foo
    teststringobj appendself2 1 3
} foo
























































if {[testConstraint testobj]} {
    testobj freeallvars
}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|



|



|



|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












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 {
    teststringobj set 1 foo
    teststringobj appendself2 1 0
} foofoo
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 {
    teststringobj set 1 foo
    teststringobj appendself2 1 2
} fooo
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
# 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.
#
# 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]]

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 {






|
|
|









|







1
2
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 © 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 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
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"

test subst-4.1 {variable substitutions} {
    set a 44
    subst {$a}
} {44}
test subst-4.2 {variable substitutions} {
    set a 44







|







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 ä ä"

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
    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}
} {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}
test subst-7.6 {switches} {
    set x 123
    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}

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}







|



|
|


|



|
|







128
129
130
131
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}
} {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}
test subst-7.6 {switches} {
    set x 123
    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}

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
# 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.
#
# 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::*






|
|
|







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 © 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::*
741
742
743
744
745
746
747







748
749
750
751
752
753
754
	switch -regexp -- {} {
	    {[012]} {return yes}
	    .+ {return yes2}
	    default {return no}
	}
    }}
} no








test switch-15.1 {coroutine safety of non-bytecoded switch} {*}{
    -body {
	proc coro {} {
	    switch -glob a {
		a {yield ok1}
	    }







>
>
>
>
>
>
>







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
# 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.
#
# 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]]

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.
#






|










|







1
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 © 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 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
	proc p args {
	    tailcall [namespace current] {*}$args
	}
	namespace delete [namespace current]
	p
    }
} -returnCodes 1 -result {namespace "::ns" not found}








# cleanup
::tcltest::cleanupTests

# Local Variables:
# mode: tcl
# End:







>
>
>
>
>
>
>







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
# 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
# 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::*
}




namespace eval ::tcltest::test {

namespace import ::tcltest::*

makeFile {
    package require tcltest 2.5




|
|

















>
>
>







1
2
3
4
5
6
7
8
9
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 © 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
#	set ::tcltest::constraintsSpecified $constraintlist
#	unset ::tcltest::testConstraints(tcltestFakeConstraint1)
#	unset ::tcltest::testConstraints(tcltestFakeConstraint2)
#    }
#}

test tcltest-5.5 {InitConstraints: list of built-in constraints} \
	-constraints {!singleTestInterp} \
	-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







|







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 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
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
    -body {
	child msg $a -tmpdir $tdiaf
	return $msg
    }
    -result {*not a directory*}
    -match glob
}
# Test non-writeable directories, non-readable directories with directory flags
set notReadableDir [file join [temporaryDirectory] notreadable]
set notWriteableDir [file join [temporaryDirectory] notwriteable]
makeDirectory notreadable
makeDirectory notwriteable

switch -- $::tcl_platform(platform) {
    unix {
	file attributes $notReadableDir -permissions 00333
	file attributes $notWriteableDir -permissions 00555
    }
    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}
    }
}
test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} {
    -constraints {unix notRoot}
    -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]]
    || $::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}
    -body {
	child msg $a -tmpdir $notWriteableDir
	return $msg
    }
    -result {*not writeable*}
    -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







|

|

|



|
|



|
|



|










|



|
|

|


|







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-writable directories, non-readable directories with directory flags
set notReadableDir [file join [temporaryDirectory] notreadable]
set notWritableDir [file join [temporaryDirectory] notwritable]
makeDirectory notreadable
makeDirectory notwritable

switch -- $::tcl_platform(platform) {
    unix {
	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 $notWritableDir -readonly 1}
	catch {testchmod 0o444 $notWritableDir}
    }
}
test tcltest-8.3 {tcltest a.tcl -tmpdir notReadableDir} {
    -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 $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 notWritableDir} {
    -constraints {unixOrWin notRoot notFAT notWsl}
    -body {
	child msg $a -tmpdir $notWritableDir
	return $msg
    }
    -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
	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}
    -body {
	child msg $a -testdir $notReadableDir
	return $msg
    }
    -match glob
    -result {*not readable*}
}







|







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 notWsl}
    -body {
	child msg $a -testdir $notReadableDir
	return $msg
    }
    -match glob
    -result {*not readable*}
}
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
    }
}

# clean up from directory testing

switch -- $::tcl_platform(platform) {
    unix {
	file attributes $notReadableDir -permissions 777
	file attributes $notWriteableDir -permissions 777
    }
    default {
	catch {testchmod 0o777 $notWriteableDir}
	catch {file attributes $notWriteableDir -readonly 0}
    }
}

file delete -force -- $notReadableDir $notWriteableDir
removeFile a.tcl
removeFile thisdirectoryisafile
removeDirectory normaldirectory

# -file, -notfile, [matchFiles], [skipFiles]
test tcltest-9.1 {-file d*.tcl} -constraints {unixOrWin} -setup {
    set old [testsDirectory]







|
|


|
|



|







716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
    }
}

# clean up from directory testing

switch -- $::tcl_platform(platform) {
    unix {
	file attributes $notReadableDir -permissions 0o777
	file attributes $notWritableDir -permissions 0o777
    }
    default {
	catch {testchmod 0o777 $notWritableDir}
	catch {file attributes $notWritableDir -readonly 0}
    }
}

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]
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
}
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]] || \
		![file exists [file join $mfdir et1.tmp]]} {
	    error "file creation didn't work"
	}
    }
    -body {
	removeFile t1.tmp
	removeFile et1.tmp $mfdir







|







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]] || \
		![file exists [file join $mfdir et1.tmp]]} {
	    error "file creation didn't work"
	}
    }
    -body {
	removeFile t1.tmp
	removeFile et1.tmp $mfdir

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
#! /usr/bin/env tclsh




package require tcltest 2.5
namespace import ::tcltest::*
testConstraint exec          [llength [info commands exec]]














testConstraint fcopy         [llength [info commands fcopy]]
testConstraint fileevent     [llength [info commands fileevent]]
testConstraint thread        [
    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
	}
    }














    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}]
    }




















































    init

    package provide tcltests 0.1
}



>
>
>


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
<















>
>
>
>
>
>
>
>
>
>
>
>

















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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 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        [expr {![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
# 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.
#
# 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.




::tcltest::loadTestedCommands
catch [list package require -exact Tcltest [info patchlevel]]
package require tcltests

# Some tests require the testthread command

testConstraint testthread [expr {[info commands testthread] ne {}}]


set threadSuperKillScript {






|
|
|












>
>
>

|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
# 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 © 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 tcl::test [info patchlevel]]


# Some tests require the testthread command

testConstraint testthread [expr {[info commands testthread] ne {}}]


set threadSuperKillScript {

Changes to tests/timer.test.

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.
#
# 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::*









|
|







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 © 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

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 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 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"
    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
    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"
    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
    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]
    update
    string length [lindex [lindex [after info $id] 0] 2]
} -cleanup {
    foreach i [after info] {
	after cancel $i
    }
} -result 5







|










|










|
|












|
|












|









|










|







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\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\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\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\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\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\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\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
# 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.
# All rights reserved.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}






|







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 © 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
    ::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
    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







|







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
    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
# 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.
#
# 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]]

testConstraint testcmdtrace [llength [info commands testcmdtrace]]
testConstraint testevalobjv [llength [info commands testevalobjv]]

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]







|
|
|










|







1
2
3
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 © 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 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
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";#}
    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} {
    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} {
    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} {
    unset -nocomplain x
    set info {}
    trace add variable x read traceScalar
    set x 123
    set info
} {}
test trace-1.4 {trace array element reads} {







|





|





|






|







72
73
74
75
76
77
78
79
80
81
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 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 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 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 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} {
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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} {
    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) ;#}
    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 ;#}
    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;#}
    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 ;#}
    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} {
    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} {
    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} {
    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} {
    #
    # 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 {
   #
   # 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} {
    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} {
    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} {
    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} {







|










|
|





|
|





|
|





|
|





|




















|







|







|














|


















|








|










|







152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
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 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 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 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 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 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 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 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 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 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 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 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 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 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
    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]
    set result
} [list [list a 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







|
|

|







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 add variable x array traceArray2
    set result [trace info variable x]
    set result
} [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
} [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"]

# 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"]







|







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, 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
	}
	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
} {}







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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.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
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} {
    namespace eval ::foo {
	variable x 123
    }
    proc p1 args {
	trace vdelete ::foo::x u p1
    }
    trace variable ::foo::x u p1
    namespace delete ::foo
    info exists ::foo::x
} 0
test trace-18.3 {namespace delete / trace vdelete 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} {
    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







|




|

|



|




|







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 remove variable combo} {
    namespace eval ::foo {
	variable x 123
    }
    proc p1 args {
	trace remove variable ::foo::x unset p1
    }
    trace add variable ::foo::x unset p1
    namespace delete ::foo
    info exists ::foo::x
} 0
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 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
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
} {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}}
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} {







|
|







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}}
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
    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 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}







|







2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
    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 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}

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
# 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.
#
# 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]]

testConstraint testchmod [llength [info commands testchmod]]



# 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
set user {}
if {[testConstraint unix]} {
    catch {set user [exec whoami]}
    if {$user == ""} {
	catch {regexp {^[^(]*\(([^)]*)\)} [exec id] dummy user}
    }
    if {$user == ""} {






|










|


>
>






|







1
2
3
4
5
6
7
8
9
10
11
12
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 © 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 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
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
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 {
    file mkdir td1/td2/td3
    file attributes td1/td2 -permissions 0000
    file rename td1/td2/td3 td2
} -returnCodes error -cleanup {
    file attributes td1/td2 -permissions 0755
    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}
test unixFCmd-1.3 {TclpRenameFile: EINVAL} -setup {
    cleanup
} -constraints {unix notRoot} -body {
    file mkdir td1
    file rename td1 td1
} -returnCodes error -cleanup {
    cleanup







|

|


|










|







92
93
94
95
96
97
98
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 notWsl} -body {
    file mkdir td1/td2/td3
    file attributes td1/td2 -permissions 0
    file rename td1/td2/td3 td2
} -returnCodes error -cleanup {
    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 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
    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 {
    file mkdir foo/bar
    file attr foo -perm 040555
    file rename foo/bar /tmp
} -returnCodes error -cleanup {
    catch {file delete /tmp/bar}
    catch {file attr foo -perm 040777}
    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}







|

|



|







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 notWsl} -body {
    file mkdir foo/bar
    file attr foo -perm 0o40555
    file rename foo/bar /tmp
} -returnCodes error -cleanup {
    catch {file delete /tmp/bar}
    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
    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 {
    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-







|







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 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
    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 {
    close [open foo.test w]
    list [file attributes foo.test -permissions 0000] \
	[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
} -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 {







|

|







|







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 notWsl} -body {
    close [open foo.test w]
    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 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
} -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} {
      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
    # message when the current directory isn't readable.
    set nd $cd/tstdir
    file mkdir $nd
    cd $nd
    file attributes $nd -permissions 0000
    pwd
} -returnCodes error -cleanup {
    cd $cd
    file attributes $nd -permissions 0755
    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







|


















|




|



|







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 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 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 0
    pwd
} -returnCodes error -cleanup {
    cd $cd
    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
# 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.
#
# 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]]

testConstraint testfindexecutable [llength [info commands testfindexecutable]]

set oldpwd [pwd]
cd [temporaryDirectory]

catch {
    set oldPath $env(PATH)
    file attributes [makeFile "" junk] -perm 0777
}
set absPath [file join [temporaryDirectory] junk]

test unixFile-1.1 {Tcl_FindExecutable} {testfindexecutable unix} {
    set env(PATH) ""
    testfindexecutable junk
} $absPath






|










|








|







1
2
3
4
5
6
7
8
9
10
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 © 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]]

testConstraint testfindexecutable [llength [info commands testfindexecutable]]

set oldpwd [pwd]
cd [temporaryDirectory]

catch {
    set oldPath $env(PATH)
    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
# 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.
#
# 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} \
    -constraints {testfork nonPortable} \
    -body {
	set myFolder [makeDirectory unixtestfork]
	set pid [testfork]
	if {$pid == 0} {
	    # we are the forked process
	    set result initialized




|
|













|







1
2
3
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 © 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 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
# 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.
#
# 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"






|
|











<
<
<







1
2
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 © 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




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
    } 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)$}
test unixInit-3.2 {TclpSetInitialEncodings} -setup {
    catch {set oldlc_all $env(LC_ALL)}


} -constraints {unix stdio} -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}

} -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)







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<















>
>
|

















>







79
80
81
82
83
84
85





















































































































































































































































86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
    } then {
	subst "OK"
    } else {
	subst "Expected: `[list 127.0.0.1 localhost $port]', Got `$result'"
    }
} {OK}






















































































































































































































































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)$}
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 knownBug} -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
# 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.
#
# 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::*






|
|







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 © 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::*

Changes to tests/unknown.test.

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.
#
# 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::*






|
|
|







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 © 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
# 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
#
# 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]]

# 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 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]
    }
}

# Basic tests: parameter testing...
test unload-1.1 {basic errors} -returnCodes error -body {
    unload
} -result {wrong # args: should be "unload ?-switch ...? fileName ?packageName? ?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?"}
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}
test unload-1.5 {basic errors} -returnCodes error -body {
    unload {} {}
} -result {must specify either file name or package name}
test unload-1.6 {basic errors} -returnCodes error -body {
    unload {} Unknown
} -result {package "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] {
    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] {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [load [file join $testDir pkgua$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 {
    loadIfNotPresent pkga
} -constraints [list $dll $loaded] -returnCodes error -match glob -body {
    unload [file join $testDir pkga$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 {
    loadIfNotPresent pkgua
} -constraints [list $dll $loaded] -body {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [unload [file join $testDir pkgua$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 {
    if {$pkgua_loaded eq ""} {
	loadIfNotPresent pkgua
	unload [file join $testDir pkgua$ext]
    }
} -constraints [list $dll $loaded] -body {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [load [file join $testDir pkgua$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 {
    # Establish expected state
    if {$pkgua_loaded eq ""} {
	loadIfNotPresent pkgua
	unload [file join $testDir pkgua$ext]
	load [file join $testDir pkgua$ext]
    }
} -constraints [list $dll $loaded] -body {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [unload [file join $testDir pkgua$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} \
	[list $dll $loaded] {
    catch {rename pkgb_sub {}}
    load [file join $testDir pkgb$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 unload-3.2 {basic loading of unloadable package in a safe interpreter, with package name conversion} \
	[list $dll $loaded] {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$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
} -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 {
    if {[lsearch -index 1 [info loaded child] Pkgb] < 0} {
	load [file join $testDir pkgb$ext] pKgB child
    }
} -constraints [list $dll $loaded] -returnCodes error -match glob -body {
    unload [file join $testDir pkgb$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 {
    if {[lsearch -index 1 [info loaded child] Pkgua] < 0} {
	load [file join $testDir pkgua$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] \
	    [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 {
    if {[child eval set pkgua_loaded] eq ""} {
	load [file join $testDir pkgua$ext] {} child
	unload [file join $testDir pkgua$ext] {} child
    }
} -constraints [list $dll $loaded] -body {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [load [file join $testDir pkgua$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 {
    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
    }
} -constraints [list $dll $loaded] -body {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [unload [file join $testDir pkgua$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 {
    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]] \
	    [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 {
    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] \
	    [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 {
    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] \
	    [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 {
    if {!$load(M)} {
	load [file join $testDir pkgua$ext]
    }
    if {!$load(C)} {
	load [file join $testDir pkgua$ext] {} child
	incr load(C)
    }
    if {!$load(T)} {
	load [file join $testDir pkgua$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]] \
	    [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 {
    if {!$load(C)} {
	load [file join $testDir pkgua$ext] {} child
    }
    if {!$load(T)} {
	load [file join $testDir pkgua$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] \
	    [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 {
    if {!$load(T)} {
	load [file join $testDir pkgua$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] \
	    [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
     } \
    -body {
	list [catch {unload simplefs:/pkgua$ext} msg] $msg
    } \
    -result {0 {}}

# cleanup
interp delete child
interp delete child-trusted
unset ext






|
|
|










|









|










<
<
<








|






|


|





|


|


|








|



|

|



|


|

|



|



|


|



|



|



|
|



|











|


|



|


|







|

|

|


|

|

|



|



|

|
|



|




|

|
|
|



|













|






|




|








|





|



|





|

|


|



|




|




|

|


|




|




|

|



|










|


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
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 © 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 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 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 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 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 ?prefix? ?interp?"}
test unload-1.2 {basic errors} -returnCodes error -body {
    unload a b c d
} -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 prefix}
test unload-1.5 {basic errors} -returnCodes error -body {
    unload {} {}
} -result {must specify either file name or prefix}
test unload-1.6 {basic errors} -returnCodes error -body {
    unload {} Unknown
} -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 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 prefix} [list $dll $loaded] {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [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 prefix} -setup {
    loadIfNotPresent pkga
} -constraints [list $dll $loaded] -returnCodes error -match glob -body {
    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 prefix} -setup {
    loadIfNotPresent pkgua
} -constraints [list $dll $loaded] -body {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [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 prefix} -setup {
    if {$pkgua_loaded eq ""} {
	loadIfNotPresent pkgua
	unload [file join $testDir tcl9pkgua$ext]
    }
} -constraints [list $dll $loaded] -body {
    list $pkgua_loaded $pkgua_detached $pkgua_unloaded \
	    [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 prefix} -setup {
    # Establish expected state
    if {$pkgua_loaded eq ""} {
	loadIfNotPresent pkgua
	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 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} \
	[list $dll $loaded] {
    catch {rename pkgb_sub {}}
    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
} {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} \
	[list $dll $loaded] {
    list [child eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [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 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 prefix} -setup {
    if {[lsearch -index 1 [info loaded child] Pkgb] < 0} {
	load [file join $testDir tcl9pkgb$ext] Pkgb child
    }
} -constraints [list $dll $loaded] -returnCodes error -match glob -body {
    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 prefix} -setup {
    if {[lsearch -index 1 [info loaded child] Pkgua] < 0} {
	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 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 prefix} -setup {
    if {[child eval set pkgua_loaded] eq ""} {
	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 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 prefix conversion} -setup {
    if {[child eval set pkgua_loaded] eq ""} {
	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 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 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 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} -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 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} -setup {
    incr load(T)
} -constraints [list $dll $loaded] -body {
    list [child-trusted eval {list $pkgua_loaded $pkgua_detached $pkgua_unloaded}] \
	    [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 prefix} -setup {
    if {!$load(M)} {
	load [file join $testDir tcl9pkgua$ext]
    }
    if {!$load(C)} {
	load [file join $testDir tcl9pkgua$ext] {} child
	incr load(C)
    }
    if {!$load(T)} {
	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 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 prefix} -setup {
    if {!$load(C)} {
	load [file join $testDir tcl9pkgua$ext] {} child
    }
    if {!$load(T)} {
	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 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 prefix} -setup {
    if {!$load(T)} {
	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 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:/tcl9pkgua$ext Pkgua
     } \
    -body {
	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
# 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.
#
# 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]
    return $z
}
proc newset {name value} {
    uplevel set $name $value
    uplevel 1 {uplevel 1 {set xyz 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
# 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 © 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}]
    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
# 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.
#
# 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]]

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






|
|
|










|







1
2
3
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 © 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 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
	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 p2 {} {upvar c x1; set x1 22}
    set x ---
    p1 foo bar
    set x
} {{x1 {} w} 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 p2 {} {upvar c x1; set x1}
    set x ---
    p1 foo bar
    set x
} {{x1 {} r} 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 p2 {} {upvar c x1; unset x1}
    set x ---
    p1 foo bar
    set x
} {{x1 {} u} x1}






























































test upvar-6.1 {retargeting an upvar} {
    proc p1 {} {
	set a(0) zeroth
	set a(1) first
	set a(2) second
	p2







|




|

|




|

|




|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
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 add var c {read write} tproc; p2}
    proc p2 {} {upvar c x1; set x1 22}
    set x ---
    p1 foo bar
    set x
} {{x1 {} write} x1}
test upvar-5.2 {traces involving upvars} {
    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 {} read} x1}
test upvar-5.3 {traces involving upvars} {
    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 {} 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
	upvar y x
	lappend result $x
	global x
	lappend result $x
    }
    p1
} {abcde 44}




























test upvar-7.1 {upvar to same level} {
    set x 44
    set y 55
    catch {unset uv}
    upvar #0 x uv
    set uv abc







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







305
306
307
308
309
310
311
312
313
314
315
316
317
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
    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}
    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 {







|







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 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 {

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
# 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.
#
# 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]]

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 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]}
} 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} {
    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]}
} 1
test utf-1.13 {Tcl_UniCharToUtf: Invalid surrogate} {Uesc testbytestring} {
    expr {"\UD842" eq [testbytestring \xEF\xBF\xBD]}
} 1




















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




|
|










|
<
<
<
<
<
<
<
<
<
<
<
<








>















|







|


<
<
<












|
|

|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17












18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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 © 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 tcl::test [info patchlevel]]













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 {"" 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 {Tcl_UniCharToUtf: 4 byte sequences} testbytestring {
    expr {"\U014E4E" eq [testbytestring \xF0\x94\xB9\x8E]}
} 1



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: Invalid surrogate} testbytestring {
    expr {"\UD842" eq [testbytestring \xED\xA1\x82]}
} 1
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
} 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]
} 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} {
    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.







<
<
<
|
|

<
<
<
|







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 {Tcl_UtfToUniChar: lead (4-byte) followed by 3 trail} {
    string length 𐀀
} 1



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
} 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} {
    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







|
<
<
<







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 {Tcl_NumUtfChars: #4-byte UTF-8 character} {testnumutfchars testbytestring} {



    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
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]
} 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







|







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 [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
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
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]
} 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]
} 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} {







|
|


















|
|

<
<
<



|
|

<
<
<







245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
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\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 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\x00]
} 1



test utf-6.31 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2]G
} 1
test utf-6.32 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\x00]
} 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
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
} 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







|







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 
} 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
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
} 3
test utf-6.63 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xA0]
} 3
test utf-6.64 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xD0]
} 3
test utf-6.65 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xE8]
} 3
test utf-6.66 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[testbytestring \xF2]
} 3
test utf-6.67 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext \u8820[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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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} {
    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]







|


|


|


|


|


|




<
<
<
|














<
<
<
|


<
<
<
|


<
<
<
|


<
<
<
|


<
<
<
|


<
<
<
|







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 G
} 3
test utf-6.63 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8\xA0\xA0\xA0]
} 3
test utf-6.64 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xD0]
} 3
test utf-6.65 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xE8]
} 3
test utf-6.66 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2]
} 3
test utf-6.67 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF8]
} 3
test utf-6.68 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0]G
} 1



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 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0]G
} 4



test utf-6.75 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xA0]
} 4



test utf-6.76 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xD0]
} 4



test utf-6.77 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xE8]
} 4



test utf-6.78 {Tcl_UtfNext} {testutfnext testbytestring} {
    testutfnext [testbytestring \xF2\xA0\xA0\xA0\xF2]
} 4



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
} 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} {
    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} {
    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]







<
<
<
|








|
<
<
<







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 {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 {Tcl_UtfNext, validity check [493dccc2de]} {testutfnext testbytestring} {



    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
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
} 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]
} 1
test utf-7.8.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xA0\xA0\xA0\xA0] 2
} 1
test utf-7.8.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \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} {
    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.2 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    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
} 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]
} 2
test utf-7.13.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xA0\xA0\xA0\xA0] 3
} 2
test utf-7.13.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \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} {
    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.2 {Tcl_UtfPrev} {testutfprev testbytestring ucs2} {
    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
} 1
test utf-7.16.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A\u8820[testbytestring \xA0] 4
} 1
test utf-7.16.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A\u8820[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} {
    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
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} {







|














|


|


|










|

|
|
|

|
<
<
<
<
<
<
<
<
<






|

















|


|


|










|

|
|
|

|
<
<
<
<
<
<

<
<
<


|


|


|










|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|







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[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 [testbytestring A\xA0]
} 1
test utf-7.8.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 2
} 1
test utf-7.8.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    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 {Tcl_UtfPrev} {testutfprev testbytestring} {
    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} {









    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[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 [testbytestring A\xA0\xA0]
} 2
test utf-7.13.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev [testbytestring A\xA0\xA0\xA0\xA0] 3
} 2
test utf-7.13.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    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 {Tcl_UtfPrev} {testutfprev testbytestring} {
    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} {






    testutfprev A[testbytestring \xF2\xA0\xA0\xF8] 4



} 1
test utf-7.16 {Tcl_UtfPrev} testutfprev {
    testutfprev A
} 1
test utf-7.16.1 {Tcl_UtfPrev} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xE8\xA0\xA0\xA0] 4
} 1
test utf-7.16.2 {Tcl_UtfPrev} {testutfprev testbytestring} {
    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} {
    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]
} 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
} 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} {
    testutfprev A[testbytestring \xF0\x80\x80\x80]
} 2
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} {







|

|







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} {
    testutfprev A[testbytestring \xF0\x80\x80\x80]
} 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
} 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} {
    testutfprev A[testbytestring \xF0\x90\x80\x80]
} 2
test utf-7.40.0 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring ucs2} {
    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} {
    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} {
    testutfprev [testbytestring \xA0\xA0\xA0\xA0]
} 1
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
} 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} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF]
} 2
test utf-7.48.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring ucs2} {
    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} {
    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} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 2
} 1
test utf-7.49.0 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring utf16} {
    testutfprev A[testbytestring \xF4\x90\x80\x80]
} 2
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
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 \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
} \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
} G
test utf-8.9.1 {Tcl_UniCharAtIndex: Emoji} ucs4 {
    string index \uD83D\uDE00G 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
} \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
} G
test utf-8.11.2 {Tcl_UniCharAtIndex: Emoji} {Uesc utf16} {
    string index \U1F600G 1
} {}
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
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
} G
test utf-9.5.1 {Tcl_UtfAtIndex: index > 0, Emoji} ucs4 {
    string range \uD83D\uDE00G 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
} \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
} G
test utf-9.7.2 {Tcl_UtfAtIndex: index > 0, Emoji} {Uesc utf16} {
    string range \U1f600G 1 1
} {}
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} {
    expr {"\U1E2165" eq "[testbytestring \xF0\x9E\x88\x96]5"}
} 1
test utf-10.7 {Tcl_UtfBackslash: stops after 6 hex chars} {Uesc fullutf 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







|

|
|

<
<
<

|
<
<
<














|

|




|




|

|
|

<
<
<

|

<
<
<

|


|

|














|
|




<
<
<
|
|
|
<
<
<





|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
|

|
|

<
<
<
|
|
<
<
<
<
<
<
<
<
<
|
|
|

|
|

<
<
<
<
<
<
<
<
<





<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
<
<
<
|
|

|
|

<
<
<
|
|
<
<
<
<
<
<
<
<
<
|
|
|

|
|

<
<
<
<
<
<
<
<
<

















|


|







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} {
    testutfprev A[testbytestring \xF0\x90\x80\x80]
} 1
test utf-7.40 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF0\x90\x80\x80] 4



} 1
test utf-7.41 {Tcl_UtfPrev -- overlong sequence}  {testutfprev testbytestring} {



    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} {
    testutfprev [testbytestring \xA0\xA0\xA0\xA0]
} 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  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} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF]
} 1
test utf-7.48.1 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 4



} 1
test utf-7.48.2 {Tcl_UtfPrev, validity check [493dccc2de]} {testutfprev testbytestring} {
    testutfprev A[testbytestring \xF4\x8F\xBF\xBF] 3



} 1
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} {
    testutfprev A[testbytestring \xF4\x90\x80\x80]
} 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 乎ɚ 0
} 
test utf-8.3 {Tcl_UniCharAtIndex: index > 0} {
    string index abcd 2
} c
test utf-8.4 {Tcl_UniCharAtIndex: index > 0} {



    string index 乎ɚÿՃ 2
} ÿ
test utf-8.5 {Tcl_UniCharAtIndex: high surrogate} {



    string index \uD842 0
} \uD842
test utf-8.6 {Tcl_UniCharAtIndex: low surrogate} {
    string index \uDC42 0
} \uDC42
test utf-8.7 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 0












} 😀



test utf-8.8 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 1
} G
test utf-8.9 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 2
} {}



test utf-8.10 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 0









} 😀
test utf-8.11 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 1
} G
test utf-8.12 {Tcl_UniCharAtIndex: Emoji} {
    string index 😀G 2
} {}










test utf-9.1 {Tcl_UtfAtIndex: index = 0} {
    string range abcd 0 2
} abc
test utf-9.2 {Tcl_UtfAtIndex: index > 0} {












    string range 乎ɚÿՃklmnop 1 5
} ɚÿՃkl
test utf-9.3 {Tcl_UtfAtIndex: index = 0, Emoji} {
    string range 😀G 0 0
} 😀



test utf-9.4 {Tcl_UtfAtIndex: index > 0, Emoji} {
    string range 😀G 1 1
} G
test utf-9.5 {Tcl_UtfAtIndex: index > 0, Emoji} {
    string range 😀G 2 2
} {}



test utf-9.6 {Tcl_UtfAtIndex: index = 0, Emoji} {
    string range 😀G 0 0









} 😀
test utf-9.7 {Tcl_UtfAtIndex: index > 0, Emoji} {
    string range 😀G 1 1
} G
test utf-9.8 {Tcl_UtfAtIndex: index > 0, Emoji} {
    string range 😀G 2 2
} {}










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} testbytestring {
    expr {"\U1E2165" eq "[testbytestring \xF0\x9E\x88\x96]5"}
} 1
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
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 \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 \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}

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
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
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
test utf-12.4 {Tcl_UtfToLower} {
    string tolower \u01E2GH
} \u01E3gh
test utf-12.5 {Tcl_UtfToLower Georgian (new in Unicode 11)} {
    string tolower \u10D0\u1C90
} \u10D0\u10D0
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-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
test utf-13.4 {Tcl_UtfToTitle} {
    string totitle \u01F3AB
} \u01F2ab
test utf-13.5 {Tcl_UtfToTitle Georgian (new in Unicode 11)} {
    string totitle \u10D0\u1C90
} \u10D0\u1C90
test utf-13.6 {Tcl_UtfToTitle Georgian (new in Unicode 11)} {
    string totitle \u1C90\u10D0
} \u1C90\u10D0
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-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
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

test utf-17.1 {Tcl_UniCharToLower, no delta} {
    string tolower !
} !

test utf-18.1 {Tcl_UniCharToTitle, add one for title} {
    string totitle \u01C4
} \u01C5
test utf-18.2 {Tcl_UniCharToTitle, subtract one for title} {
    string totitle \u01C6
} \u01C5
test utf-18.3 {Tcl_UniCharToTitle, subtract delta for title (positive)} {
    string totitle \u017F
} \x53
test utf-18.4 {Tcl_UniCharToTitle, subtract delta for title (negative)} {
    string totitle \xFF
} \u0178
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 {
    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 {
    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} {
    # this returns 1 with Unicode 7 compliance
    string is alnum \u1040\u021F\u0220
} 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]
} {1 1}
test utf-21.3 {unicode print char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    regexp {^[[:print:]]+$} \uFBC1
} 1
test utf-21.4 {TclUniCharIsGraph} {
    # [Bug 3464428]
    string is graph \u0120
} 1
test utf-21.5 {unicode graph char in regc_locale.c} {
    # [Bug 3464428]
    regexp {^[[:graph:]]+$} \u0120
} 1
test utf-21.6 {TclUniCharIsGraph} {
    # [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} {
    # [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} {
    # [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} {
    string wordend "xyz123_bar fg" 0
} 10
test utf-22.2 {TclUniCharIsWordChar} {
    string wordend "x\u5080z123_bar\u203C fg" 0
} 10

test utf-23.1 {TclUniCharIsAlpha} {
    # this returns 1 with Unicode 7 compliance
    string is alpha \u021F\u0220\u037F\u052F
} 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
} 1

test utf-24.1 {TclUniCharIsDigit} {
    # this returns 1 with Unicode 7 compliance
    string is digit \u1040\uABF0
} 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]
} {1 1}

test utf-24.3 {TclUniCharIsSpace} {
    # 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 {
    # 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}







<
|








<
|


|
|
|
|
|
|
|
|
|
|
|
|
|
|
|











|
|

|
|
|
|
|
|
|
|











|
|

|
|

|
|



|
|
|
|
|
|








|
|

|
|

|
|

|
|



|
|
|
|
|
|


















|
|








|
|






|
|

|
|

|
|

|
|










|


|









|

|



|



|

|

|



|

|







|











|








|


|
|


|

|



|


|

|



|


|







|







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	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    60
bsCheck \U      85
bsCheck \Uk     85
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 ǣgh
} ǢGH
test utf-11.5 {Tcl_UtfToUpper Georgian (new in Unicode 11)} {
    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 ÃGH
} ãgh
test utf-12.4 {Tcl_UtfToLower} {
    string tolower ǢGH
} ǣgh
test utf-12.5 {Tcl_UtfToLower Georgian (new in Unicode 11)} {
    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} {
    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 ãGH
} Ãgh
test utf-13.4 {Tcl_UtfToTitle} {
    string totitle dzAB
} Dzab
test utf-13.5 {Tcl_UtfToTitle Georgian (new in Unicode 11)} {
    string totitle აᲐ
} აᲐ
test utf-13.6 {Tcl_UtfToTitle Georgian (new in Unicode 11)} {
    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} {
    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 Ÿÿ
} ŸŸ
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 ŸÿꞍDž
} ÿÿɥdž

test utf-17.1 {Tcl_UniCharToLower, no delta} {
    string tolower !
} !

test utf-18.1 {Tcl_UniCharToTitle, add one for title} {
    string totitle DŽ
} Dž
test utf-18.2 {Tcl_UniCharToTitle, subtract one for title} {
    string totitle dž
} Dž
test utf-18.3 {Tcl_UniCharToTitle, subtract delta for title (positive)} {
    string totitle ſ
} S
test utf-18.4 {Tcl_UniCharToTitle, subtract delta for title (negative)} {
    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} {
    string compare [string range [format %c 0xFFFF] 0 0] [string range [format %c 0x10000] 0 0]
} -1
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 {Tcl_UniCharIsAlnum} {
    # this returns 1 with Unicode 7 compliance
    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:]]+$} ၀ȟȠ] [regexp {^\w+$} ၀ȟȠ_‿⁀⁔︳︴﹍﹎﹏_]
} {1 1}
test utf-21.3 {unicode print char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    regexp {^[[:print:]]+$} 
} 1
test utf-21.4 {Tcl_UniCharIsGraph} {
    # [Bug 3464428]
    string is graph Ġ
} 1
test utf-21.5 {unicode graph char in regc_locale.c} {
    # [Bug 3464428]
    regexp {^[[:graph:]]+$} Ġ
} 1
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 {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 {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 {Tcl_UniCharIsWordChar} {
    string wordend "xyz123_bar fg" 0
} 10
test utf-22.2 {Tcl_UniCharIsWordChar} {
    string wordend "xz123_bar fg" 0
} 10

test utf-23.1 {Tcl_UniCharIsAlpha} {
    # this returns 1 with Unicode 7 compliance
    string is alpha ȟȠͿԯ
} 1
test utf-23.2 {unicode alpha char in regc_locale.c} {
    # this returns 1 with Unicode 7 compliance
    regexp {^[[:alpha:]]+$} ȟȠͿԯ
} 1

test utf-24.1 {Tcl_UniCharIsDigit} {
    # this returns 1 with Unicode 7 compliance
    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:]]+$} ၀꯰] [regexp {^\d+$} ၀꯰]
} {1 1}

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 {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
    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}


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 {}

# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|
|
|
|













>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|








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]
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 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
# This file contains a collection of tests for Tcl_UtfToExternal and
# Tcl_UtfToExternal. Sourcing this file into Tcl runs the tests and generates
# errors. No output means no errors found.
#
# 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]]

# Maps encoded bytes string to utf-8 equivalents, both in hex
# encoding utf-8 encdata
lappend utfExtMap {*}{
    ascii 414243 414243
}

# Simple test with basic flags
proc testbasic {direction enc hexin hexout {flags {start end}}} {
    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

    # The C wrapper fills entire destination buffer with FF.
    # Anything beyond expected output should have FF's
    set filler [string repeat \xFF $dstlen]
    set result [string range "$out$filler" 0 $dstlen-1]
    test $cmd-$enc-$hexin-[join $flags -] "$cmd - $enc - $hexin - $flags" -body \
        [list testencoding $cmd $enc $in $flags {} $dstlen] \
        -result [list ok {} $result] -constraints testencoding
    foreach profile [encoding profiles] {
        set flags2 [linsert $flags end profile$profile]
        test $cmd-$enc-$hexin-[join $flags2 -] "$cmd - $enc - $hexin - $flags" -body \
            [list testencoding $cmd $enc $in $flags2 {} $dstlen] \
            -result [list ok {} $result] -constraints testencoding
    }
}

#
# Basic tests
foreach {enc utfhex hex} $utfExtMap {
    # Basic test - TCL_ENCODING_START|TCL_ENCODING_END
    # Note by default output should be terminated with \0
    testbasic toutf $enc $hex ${utfhex}00 {start end}
    testbasic fromutf $enc $utfhex ${hex}00 {start end}

    # Test TCL_ENCODING_NO_TERMINATE
    testbasic toutf $enc $hex $utfhex {start end noterminate}
    # knownBug - noterminate not obeyed by fromutf
    # testbasic fromutf $enc $utfhex $hex {start end noterminate}
}

# Test for insufficient space
test xx-bufferoverflow {buffer overflow Tcl_ExternalToUtf} -body {
    testencoding Tcl_UtfToExternal utf-16 A {start end} {} 1
} -result [list nospace {} \xFF] -constraints testencoding

# Another bug - char limit not obeyed
# % set cv 2
# % testencoding Tcl_ExternalToUtf utf-8 abcdefgh {start end noterminate charlimit} {} 20 rv wv cv
# nospace {} abcÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

test TableToUtf-bug-5be203d6ca {Bug 5be203d6ca - truncated prefix in table encoding} -body {
    set src \x82\x4F\x82\x50\x82
    lassign [testencoding Tcl_ExternalToUtf shiftjis $src {start profiletcl8} 0 16 srcRead dstWritten charsWritten] buf
    set result [list [testencoding Tcl_ExternalToUtf shiftjis $src {start profiletcl8} 0 16 srcRead dstWritten charsWritten] $srcRead $dstWritten $charsWritten]
    lappend result {*}[list [testencoding Tcl_ExternalToUtf shiftjis [string range $src $srcRead end] {end profiletcl8} 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


::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
# 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.
#
# 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]]

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]]


# 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xf0\x7f d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\x7f d \
		ieeeValues(NaN)
	    binary scan \x00\x00\x00\x00\x00\x00\xf8\xff d \
		ieeeValues(-NaN)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7f\xf0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7f\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    binary scan \xff\xf8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-NaN)
	    binary scan \xff\xfb\x45\x67\x89\xab\xcd\xef d \
		ieeeValues(-NaN(3456789abcdef))
	    set ieeeValues(littleEndian) 0
	    return 1
	}
	default {
	    return 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
51
52
53
54
55
56
57
58
59
60
61
62
63
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 © 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 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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
		ieeeValues(+Infinity)
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
		ieeeValues(NaN)
	    binary scan \x00\x00\x00\x00\x00\x00\xF8\xFF d \
		ieeeValues(-NaN)
	    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 \
		ieeeValues(-Infinity)
	    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 \
		ieeeValues(+Normal)
	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(+Infinity)
	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(NaN)
	    binary scan \xFF\xF8\x00\x00\x00\x00\x00\x00 d \
		ieeeValues(-NaN)
	    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
    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]
    } 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







|







99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    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}]
    } 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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214



215
216
217
218
219
220
221
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
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
} {}




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







|
|
|





>
>
>







201
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
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
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
} 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
} 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"
} 1
test util-5.14 {Tcl_StringMatch} {
    # if ((*pattern == ']') || (*pattern == '\0'))
    # badly formed pattern
    Wrapper_Tcl_StringMatch {[]} {[]}
} 0
test util-5.15 {Tcl_StringMatch} {
    # if ((*pattern == ']') || (*pattern == '\0'))
    # 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"
} 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]
} 0
test util-5.19 {Tcl_StringMatch: UTF-8} {
    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
    # proper advance.
    Wrapper_Tcl_StringMatch {a[a\u4e4fc]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"
} 0
test util-5.23 {Tcl_StringMatch: UTF-8 range} {
    Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "\u4e33"
} 1
test util-5.24 {Tcl_StringMatch: UTF-8 range} {
    Wrapper_Tcl_StringMatch "\[\u4e00-\u4e4f]" "\uff08"
} 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







|






|












|


|




|









|



|
|




|








|


|


|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
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 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 ac
} 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 "\[xy\]bc" "bc"
} 1
test util-5.14 {Tcl_StringMatch} {
    # if ((*pattern == ']') || (*pattern == '\x00'))
    # badly formed pattern
    Wrapper_Tcl_StringMatch {[]} {[]}
} 0
test util-5.15 {Tcl_StringMatch} {
    # 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\[ac]c" "ac"
} 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 
    Wrapper_Tcl_StringMatch {a[ac]c} [testbytestring a\x8Fc]
} 0
test util-5.19 {Tcl_StringMatch: UTF-8} {
    # pattern += Tcl_UtfToUniChar(pattern, &endChar);
    # proper advance.
    Wrapper_Tcl_StringMatch {a[ac]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 "\[-]" "0"
} 0
test util-5.23 {Tcl_StringMatch: UTF-8 range} {
    Wrapper_Tcl_StringMatch "\[-]" ""
} 1
test util-5.24 {Tcl_StringMatch: UTF-8 range} {
    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
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
} 0
test util-5.43 {Tcl_StringMatch: skip correct number of ']'} {
    Wrapper_Tcl_StringMatch \[A-]\ue1]x \ue1x
} 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')
    # 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} {







|


|





|







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} \xE1x
} 0
test util-5.43 {Tcl_StringMatch: skip correct number of ']'} {
    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 == '\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
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
} 0


test util-6.5 {Tcl_PrintDouble - make sure there's a decimal point} {
    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]
} {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
    set result [interp target {} fooset]
    interp delete \u5420
    set result
} "\u5420 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 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 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







|




|


|










|
|
|

|

|






|






|







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\x00 a\x80
} 0


test util-6.5 {Tcl_PrintDouble - make sure there's a decimal point} {
    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}]
} {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 
    interp create [list  foo]
    interp alias {} fooset [list  foo] set
    set result [interp target {} fooset]
    interp delete 
    set result
} " 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  -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 \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
    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} {
    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} {
    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} {
    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} {
    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} {
    testdstring free
    testdstring append {\\\\\\\\ } -1
    testdstring start
    testdstring end

    # Should make {\\\\\\\\ {}}
    list [llength [testdstring get]] [string index [testdstring get] 9]







|








|








|








|








|







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} 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} 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} 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} 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} 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
    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
} {1.1e-5}
test util-11.2 {Tcl_PrintDouble - scaling} {
    expr 1.1e-4
} {0.00011}
test util-11.3 {Tcl_PrintDouble - scaling} {
    expr 1.1e-3
} {0.0011}
test util-11.4 {Tcl_PrintDouble - scaling} {
    expr 1.1e-2
} {0.011}
test util-11.5 {Tcl_PrintDouble - scaling} {
    expr 1.1e-1
} {0.11}
test util-11.6 {Tcl_PrintDouble - scaling} {
    expr 1.1e0
} {1.1}
test util-11.7 {Tcl_PrintDouble - scaling} {
    expr 1.1e1
} {11.0}
test util-11.8 {Tcl_PrintDouble - scaling} {
    expr 1.1e2
} {110.0}
test util-11.9 {Tcl_PrintDouble - scaling} {
    expr 1.1e3
} {1100.0}
test util-11.10 {Tcl_PrintDouble - scaling} {
    expr 1.1e4
} {11000.0}
test util-11.11 {Tcl_PrintDouble - scaling} {
    expr 1.1e5
} {110000.0}
test util-11.12 {Tcl_PrintDouble - scaling} {
    expr 1.1e6
} {1100000.0}
test util-11.13 {Tcl_PrintDouble - scaling} {
    expr 1.1e7
} {11000000.0}
test util-11.14 {Tcl_PrintDouble - scaling} {
    expr 1.1e8
} {110000000.0}
test util-11.15 {Tcl_PrintDouble - scaling} {
    expr 1.1e9
} {1100000000.0}
test util-11.16 {Tcl_PrintDouble - scaling} {
    expr 1.1e10
} {11000000000.0}
test util-11.17 {Tcl_PrintDouble - scaling} {
    expr 1.1e11
} {110000000000.0}
test util-11.18 {Tcl_PrintDouble - scaling} {
    expr 1.1e12
} {1100000000000.0}
test util-11.19 {Tcl_PrintDouble - scaling} {
    expr 1.1e13
} {11000000000000.0}
test util-11.20 {Tcl_PrintDouble - scaling} {
    expr 1.1e14
} {110000000000000.0}
test util-11.21 {Tcl_PrintDouble - scaling} {
    expr 1.1e15
} {1100000000000000.0}
test util-11.22 {Tcl_PrintDouble - scaling} {
    expr 1.1e16
} {11000000000000000.0}
test util-11.23 {Tcl_PrintDouble - scaling} {
    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







|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|


|







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}
} {1.1e-5}
test util-11.2 {Tcl_PrintDouble - scaling} {
    expr {1.1e-4}
} {0.00011}
test util-11.3 {Tcl_PrintDouble - scaling} {
    expr {1.1e-3}
} {0.0011}
test util-11.4 {Tcl_PrintDouble - scaling} {
    expr {1.1e-2}
} {0.011}
test util-11.5 {Tcl_PrintDouble - scaling} {
    expr {1.1e-1}
} {0.11}
test util-11.6 {Tcl_PrintDouble - scaling} {
    expr {1.1e0}
} {1.1}
test util-11.7 {Tcl_PrintDouble - scaling} {
    expr {1.1e1}
} {11.0}
test util-11.8 {Tcl_PrintDouble - scaling} {
    expr {1.1e2}
} {110.0}
test util-11.9 {Tcl_PrintDouble - scaling} {
    expr {1.1e3}
} {1100.0}
test util-11.10 {Tcl_PrintDouble - scaling} {
    expr {1.1e4}
} {11000.0}
test util-11.11 {Tcl_PrintDouble - scaling} {
    expr {1.1e5}
} {110000.0}
test util-11.12 {Tcl_PrintDouble - scaling} {
    expr {1.1e6}
} {1100000.0}
test util-11.13 {Tcl_PrintDouble - scaling} {
    expr {1.1e7}
} {11000000.0}
test util-11.14 {Tcl_PrintDouble - scaling} {
    expr {1.1e8}
} {110000000.0}
test util-11.15 {Tcl_PrintDouble - scaling} {
    expr {1.1e9}
} {1100000000.0}
test util-11.16 {Tcl_PrintDouble - scaling} {
    expr {1.1e10}
} {11000000000.0}
test util-11.17 {Tcl_PrintDouble - scaling} {
    expr {1.1e11}
} {110000000000.0}
test util-11.18 {Tcl_PrintDouble - scaling} {
    expr {1.1e12}
} {1100000000000.0}
test util-11.19 {Tcl_PrintDouble - scaling} {
    expr {1.1e13}
} {11000000000000.0}
test util-11.20 {Tcl_PrintDouble - scaling} {
    expr {1.1e14}
} {110000000000000.0}
test util-11.21 {Tcl_PrintDouble - scaling} {
    expr {1.1e15}
} {1100000000000000.0}
test util-11.22 {Tcl_PrintDouble - scaling} {
    expr {1.1e16}
} {11000000000000000.0}
test util-11.23 {Tcl_PrintDouble - scaling} {
    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
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
	0x1ffffffffffffd000
	0x1ffffffffffffd800
	0x1ffffffffffffe000
	0x1ffffffffffffe800
	0x1fffffffffffff000
	0x1fffffffffffff800
    } {
	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
	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]
} {9223372036854775807}

test util-18.2 {Tcl_ObjPrintf} {testprint} {
    testprint %I64d [expr 2**63-1]
} {9223372036854775807}

test util-18.3 {Tcl_ObjPrintf} {testprint} {
    testprint %qd [expr 2**63-1]
} {9223372036854775807}

test util-18.4 {Tcl_ObjPrintf} {testprint} {
    testprint %jd [expr 2**63-1]
} {9223372036854775807}

test util-18.5 {Tcl_ObjPrintf} {testprint} {
    testprint %lld [expr -2**63]
} {-9223372036854775808}

test util-18.6 {Tcl_ObjPrintf} {testprint} {
    testprint %I64d [expr -2**63]
} {-9223372036854775808}

test util-18.7 {Tcl_ObjPrintf} {testprint} {
    testprint %qd [expr -2**63]
} {-9223372036854775808}

test util-18.8 {Tcl_ObjPrintf} {testprint} {
    testprint %jd [expr -2**63]
} {-9223372036854775808}

test util-18.9 {Tcl_ObjPrintf} {testprint} {
    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}









# cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|

|















|



|



|



|



|



|



|



|



|













>
>
>
>
>
>
>
>








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
	lappend r [format %#llx $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}]
} {9223372036854775807}

test util-18.2 {Tcl_ObjPrintf} {testprint} {
    testprint %I64d [expr {2**63-1}]
} {9223372036854775807}

test util-18.3 {Tcl_ObjPrintf} {testprint} {
    testprint %qd [expr {2**63-1}]
} {9223372036854775807}

test util-18.4 {Tcl_ObjPrintf} {testprint} {
    testprint %jd [expr {2**63-1}]
} {9223372036854775807}

test util-18.5 {Tcl_ObjPrintf} {testprint} {
    testprint %lld [expr {-2**63}]
} {-9223372036854775808}

test util-18.6 {Tcl_ObjPrintf} {testprint} {
    testprint %I64d [expr {-2**63}]
} {-9223372036854775808}

test util-18.7 {Tcl_ObjPrintf} {testprint} {
    testprint %qd [expr {-2**63}]
} {-9223372036854775808}

test util-18.8 {Tcl_ObjPrintf} {testprint} {
    testprint %jd [expr {-2**63}]
} {-9223372036854775808}

test util-18.9 {Tcl_ObjPrintf} {testprint} {
    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
# 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.
#
# 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]]

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 {} {










|
|










|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 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 © 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 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 {} {
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
	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}
} -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}]] \
} -cleanup {
    rename p {}
} -result [lrepeat 3 [list \u20ac \xe4]]
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]}
} -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]}]] \
} -cleanup {
    rename p {}
} -result [lrepeat 3 [list v\u20ac v\xe4]]

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 {







|




|
|


|

|




|
|


|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
	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  ä] {info vars}
} -body {
    # test variable with non-ascii name is available (euro and a-uml chars here):
    list \
	[p 1 2] \
	[apply [list [list  ä] {info vars}] 1 2] \
	[apply [list [list [list  ] [list ä ä]] {info vars}]] \
} -cleanup {
    rename p {}
} -result [lrepeat 3 [list  ä]]
test var-1.21 {TclLookupVar, regression on utf-8 variable names} -setup {
    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  ä] {list [set ] [set ä]}] v vä] \
	[apply [list [list [list  v] [list ä vä]] {list [set ] [set ä]}]] \
} -cleanup {
    rename p {}
} -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 {
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
    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
    }
    list [lsort [info vars test_ns_var::*]] \
         [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 ""







|







449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
    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
    }
    list [lsort [info vars test_ns_var::*]] \
         [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 ""
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
    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]
    }
    list [unset test_ns_var::v] $test_ns_var::info
} -result {{} {test_ns_var::v {} u}}
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
    }
    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}}

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
	}
	namespace delete n
    }
} -cleanup {
    rename ::t {}
} -result 0








|


|







|





|









|







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
    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 add var v unset [namespace code traceUnset]
    }
    list [unset test_ns_var::v] $test_ns_var::info
} -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 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 {} 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 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
} -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]
    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
    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
    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
    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}







|
|







|










|
|







|







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 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 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 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 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
} -body {
    proc foo {var ind op} {
	global t
	set foo bar
    }
    namespace eval :: {
	set t(1) 1
	trace variable t(1) u 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}







|







791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
} -body {
    proc foo {var ind op} {
	global t
	set foo bar
    }
    namespace eval :: {
	set t(1) 1
	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}
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
        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 {
    proc doit {} {
	interp create child
	child eval {
	    proc doit script {
		eval $script
		set foo bar
	    }







|







1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
        set end [getbytes]
    }
    set leakedBytes [expr {$end - $tmp}]
} -cleanup {
    array unset A
    rename doit {}
} -result 0
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
	    }
1476
1477
1478
1479
1480
1481
1482







































































































































































































































































































































































































































































































































































































































































































































































































1483
1484
1485
1486
1487
1488
1489
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








































































































































































































































































































































































































































































































































































































































































































































































































catch {namespace delete ns}
catch {unset arr}
catch {unset v}

catch {rename getbytes ""}
catch {rename p ""}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
# 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.
#
# 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]}
    set count
} 10
test while-old-1.2 {basic while loops} {
    set value xxx
    while {2 > 3} {set value yyy}
    set value
} xxx








|
|
|











|







1
2
3
4
5
6
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 © 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}]}
    set count
} 10
test while-old-1.2 {basic while loops} {
    set value xxx
    while {2 > 3} {set value yyy}
    set value
} xxx
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
} {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}
	set result [concat $result [lindex $list $index]]
	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 result
} {1 2 3}

test while-old-4.1 {errors in while loops} {
    set err [catch {while} msg]
    list $err $msg







|

|











|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
} {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}
	set result [concat $result [lindex $list $index]]
	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 result
} {1 2 3}

test while-old-4.1 {errors in while loops} {
    set err [catch {while} msg]
    list $err $msg

Changes to tests/while.test.

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.
#
# 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::*






|
|







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 © 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::*
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
} -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
	set a [concat $a $i]
        incr i
    }
    return $a
} -cleanup {
    unset a i
} -result {1 2 3}







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
} -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
	set a [concat $a $i]
        incr i
    }
    return $a
} -cleanup {
    unset a i
} -result {1 2 3}
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>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







|
|







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>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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
    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}]
    return $a
} -cleanup {
    unset a i
} -result {}

# Check "while" and "continue".








|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
    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}]
    return $a
} -cleanup {
    unset a i
} -result {}

# Check "while" and "continue".

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
} -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>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







|
|
|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
} -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>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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
} -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>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>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







|
|
|















|







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
} -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>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>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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
    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
	set a [concat $a $i]
        incr i
    }
    return $a
} -cleanup {
    unset a i z
} -result {1 2 3}







|







397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
    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
	set a [concat $a $i]
        incr i
    }
    return $a
} -cleanup {
    unset a i z
} -result {1 2 3}
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>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







|
|







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>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
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
    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}]
    return $a
} -cleanup {
    unset a i z
} -result {}

# Check "break" with computed command names.








|







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
    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}]
    return $a
} -cleanup {
    unset a i z
} -result {}

# Check "break" with computed command names.

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
    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>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>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







|
|
|















|







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
    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>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>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
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
    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>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







|
|
|







633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
    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>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

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
# 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.

#
# 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 winConsole-1.1 {Console file channel: non-blocking gets} {win interactive} {





    set oldmode [fconfigure stdin]

    puts stdout "Enter abcdef<return> now: " nonewline
    flush stdout
    fileevent stdin readable {
	if {[gets stdin line] >= 0} {


	    set result $line
	} else {



	    set result "gets failed"
	}
    }

    fconfigure stdin -blocking 0 -buffering line


























    set result {}



    vwait result

    #cleanup the fileevent
    fileevent stdin readable {}





















    fconfigure stdin {*}$oldmode























    set result










}  "abcdef"























































































































































































































































#cleanup






::tcltest::cleanupTests
return







|
>









>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>


|
<


>
>
|
|
>
>
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
>
>
>




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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.
#
# 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 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]

    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 "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 "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}

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 {
    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
# 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.
#
# 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 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]}]} {
	testConstraint dde 1
    }
}
testConstraint notWine [expr {$::tcl_platform(platform) ne "windows" || ![info exists ::env(TRAVIS_OS_NAME)] || ![string match linux $::env(TRAVIS_OS_NAME)]}]


# -------------------------------------------------------------------------
# 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+]

    puts $f [list set ddeServerName $ddeServerName]
    puts $f [list load $::ddelib dde]
    puts $f {
        # DDE child server -
        #
	if {"::tcltest" ni [namespace children]} {
	    package require tcltest 2.5
	    namespace import -force ::tcltest::*
	}






|








>

<




|
|



|












>

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

18
19
20
21
22
23
24
25
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 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 © 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 dde 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    set ::ddever [package require dde 1.4.5]
	    set ::ddelib [info loaded {} Dde]}]} {
	testConstraint dde 1
    }
}
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 {
        # DDE child server -
        #
	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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
	vwait reallyDone
	exit
    }
    close $f

    # run the child server script.
    set f [open |[list [interpreter] $::scriptName] r]
    fconfigure $f -buffering line
    gets $f line
    return $f
}

# -------------------------------------------------------------------------
test winDde-1.0 {check if we are testing the right dll} {win dde} {
    set ::ddever
} {1.4.3}

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
} -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
} -result 1
test winDde-2.4 {Checking for existence, with only the topic specified} \
	-constraints dde -body {
    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
} -result foo
test winDde-3.2 {DDE execute -async locally} -constraints dde -body {
    set \xe1 ""
    dde execute -async TclEval self [list set \xe1 foo]
    update
    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
} -result foo
test winDde-3.4 {DDE eval locally} -constraints dde -body {
    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
} -result "foo\x00"
# 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
} -result 196
# Set variable a to A with diaeresis (unicode C4) using binary execute
# and compose utf-8 (e.g. "c3 84" ) manualy
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
} -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
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

# -------------------------------------------------------------------------

test winDde-4.1 {DDE execute remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set name ch\xEDld-4.1
    set child [createChildProcess $name]
    dde execute TclEval $name [list set \xe1 foo]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
} -result ""
test winDde-4.2 {DDE execute async remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set name ch\xEDld-4.2
    set child [createChildProcess $name]
    dde execute -async TclEval $name [list set \xe1 foo]
    update
    dde execute TclEval $name {set done 1}
    update
    set \xe1
} -result ""
test winDde-4.3 {DDE request remotely} -constraints {dde stdio} -body {
    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 {set done 1}
    update
    set \xe1
} -result foo
test winDde-4.4 {DDE eval remotely} -constraints {dde stdio} -body {
    set \xe1 ""
    set name ch\xEDld-4.4
    set child [createChildProcess $name]
    set \xe1 [dde eval $name set \xe1 foo]
    dde execute TclEval $name {set done 1}
    update
    set \xe1
}  -result foo
test winDde-4.5 {DDE poke remotely} -constraints {dde debug stdio} -body {
    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 execute TclEval $name {set done 1}
    update
    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"}







|







|






|







|



|





|
|
|


|
|

|


|
|
|


|
|


|
|
|

|


|
|
|

|
|

|
|
|


|
|
|
|

|
|
|
|




|


|


|


|


|



|


|


|
|


|


|


|


|


|


|
|


|







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
	vwait reallyDone
	exit
    }
    close $f

    # run the child server script.
    set f [open |[list [interpreter] $::scriptName] r]
    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.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}
} -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}
} -result 1
test winDde-2.4 {Checking for existence, with only the topic specified} \
	-constraints dde -body {
    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
} -result foo
test winDde-3.2 {DDE execute -async locally} -constraints dde -body {
    set \xE1 ""
    dde execute -async TclEval self [list set \xE1 foo]
    update
    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
} -result foo
test winDde-3.4 {DDE eval locally} -constraints dde -body {
    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
} -result "foo\x00"
# 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
} -result 196
# 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
} -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
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

# -------------------------------------------------------------------------

test winDde-4.1 {DDE execute remotely} -constraints {dde stdio} -body {
    set \xE1 ""
    set name ch\xEDld-4.1
    set child [createChildProcess $name]
    dde execute TclEval $name [list set \xE1 foo]
    dde execute TclEval $name {set done 1}
    update
    set \xE1
} -result ""
test winDde-4.2 {DDE execute async remotely} -constraints {dde stdio} -body {
    set \xE1 ""
    set name ch\xEDld-4.2
    set child [createChildProcess $name]
    dde execute -async TclEval $name [list set \xE1 foo]
    update
    dde execute TclEval $name {set done 1}
    update
    set \xE1
} -result ""
test winDde-4.3 {DDE request remotely} -constraints {dde stdio} -body {
    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 {set done 1}
    update
    set \xE1
} -result foo
test winDde-4.4 {DDE eval remotely} -constraints {dde stdio} -body {
    set \xE1 ""
    set name ch\xEDld-4.4
    set child [createChildProcess $name]
    set \xE1 [dde eval $name set \xE1 foo]
    dde execute TclEval $name {set done 1}
    update
    set \xE1
}  -result foo
test winDde-4.5 {DDE poke remotely} -constraints {dde debug stdio} -body {
    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 execute TclEval $name {set done 1}
    update
    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
} -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
} -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 {







|
|







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
} -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
# 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.
#
# 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]]

# 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


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)]}]

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*]

	}
	if {$x != ""} {
	    catch {file delete -force -- {*}$x}
	}
    }
}

if {[testConstraint win]} {
    if {$::tcl_platform(osVersion) >= 5.0} {
	testConstraint winVista 1
    } else {
	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 *] {






|
|










|



<
<






>
>
|
|















|
|
|
|
>
|
>
|
<
|
|
|
<
|
<
<
|
|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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 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 © 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 tcl::test [info patchlevel]]

# Initialise the test constraints



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 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 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*]
        }

        file delete -force $victim
    }
}

proc cleanup {args} {


    foreach p [list [pwd] {*}$args] {
        cleanupRecurse {*}[glob -nocomplain -directory $p tf* td*]

    }
}

# find a CD-ROM so we can test read-only filesystems.

proc findfile {dir} {
    foreach p [glob -nocomplain -type f -directory $dir *] {
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
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.

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 {
    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 {
    testfile mv / td1
} -returnCodes error -result EINVAL
test winFCmd-1.4 {TclpRenameFile: errno: EINVAL} -setup {
    cleanup
} -constraints {win testfile notWine} -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 {
    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 {







|






|






|




|





|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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.

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 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 notInCIenv} -body {
    testfile mv / td1
} -returnCodes error -result EINVAL
test winFCmd-1.4 {TclpRenameFile: errno: EINVAL} -setup {
    cleanup
} -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 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
} -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 {







<
<
<
<
<







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.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
    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 {
    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 {

    testfile mv / c:/
} -returnCodes error -result EINVAL
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 {







<
<
<
<
<



















|






>

|







220
221
222
223
224
225
226





227
228
229
230
231
232
233
234
235
236
237
238
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.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 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|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
} -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 {
    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 {
    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 {
    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 {







|






|






|







285
286
287
288
289
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 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 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 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
    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 {
    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 {







|







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 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 {
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

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
    }
}

test winFCmd-1.38 {TclpRenameFile: check rename of conflicting inodes} -setup {
    cleanup
} -constraints {win winNonZeroInodes knownMsvcBug notWine} -body {
    file mkdir td1
    foreach {a b} [MakeFiles td1] break
    file rename -force $a $b
    file exists $a
} -cleanup {
    cleanup
} -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







|















|

|




|







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

proc MakeFiles {dirname} {
    set inodes {}
    set ndx -1
    while {1} {
        # 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 notInCIenv extensive} -body {
    file mkdir td1
    lassign [MakeFiles td1] a b
    file rename -force $a $b
    file exists $a
} -cleanup {
    cleanup
} -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
    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 {







<
<
<
<
<







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.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
    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 {
    createfile tf1 tf1
    testchmod 0 tf1
    testfile cp tf1 tf2
    list [contents tf2] [file writable tf2]
} -cleanup {
    catch {testchmod 0o666 tf1}
    cleanup
} -result {tf1 0}
test winFCmd-2.13 {TclpCopyFile: CopyFile fails} -setup {
    cleanup
} -constraints {win testfile} -body {
    createfile tf1
    file mkdir td1







|

|



|







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 testchmod} -body {
    createfile tf1 tf1
    file attribute tf1 -readonly 1
    testfile cp tf1 tf2
    list [contents tf2] [file writable tf2]
} -cleanup {
    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
    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
    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 {







|



<







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
    file attribute tf2 -readonly 1
    testfile cp tf1 tf2
    list [file writable tf2] [contents tf2]
} -cleanup {

    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
    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 {







<







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

    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
    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
} -returnCodes error -cleanup {
    catch {testchmod 0o666 td1}
    cleanup
} -result {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} {
    # 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 {







|
>
>
>
|
|
>
|
|

<

|







|







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 {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 {

    cleanup
} -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 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
# 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 {
    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 {
    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
} -cleanup {
    catch {testchmod 0o666 td1}
    cleanup
} -returnCodes error -result {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}}







|
<
<
<
<
<
<
<
<
<
<


|






|
>
>
>
|
|
>
|
|

|

|







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}}
# winFCmd-6.9 removed - was exact dup of winFCmd-6.1










test winFCmd-6.11 {TclpRemoveDirectory: attr == -1} -setup {
    cleanup
} -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 {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 {
    testchmod 0o770 td0/td1
    cleanup
} -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
    # 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 0 td1
    testfile cpdir td1 td2
    list [file exists td2] [file writable td2]
} -cleanup {
    catch {testchmod 0o666 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







>
|



|







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 0o400 td1
    testfile cpdir td1 td2
    list [file exists td2] [file writable td2]
} -cleanup {
    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
    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 0 td1
    testfile cpdir td1 td2
    list [file exists td2] [file writable td2]
} -cleanup {
    catch {testchmod 0o666 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







>
|



|







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 0o400 td1
    testfile cpdir td1 td2
    list [file exists td2] [file writable td2]
} -cleanup {
    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
    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 0 td1
    testfile cpdir td1 td2
    list [file writable td1] [file writable td1/td2]
} -cleanup {
    catch {testchmod 0o666 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
    file exists td1
} -cleanup {
    catch {testchmod 0o666 td1}
    cleanup
} -returnCodes error -result {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 {}








>
|



|




















|
>
>
>
|
|
>
|


|

|







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 0o400 td1
    testfile cpdir td1 td2
    list [file writable td1] [file writable td1/td2]
} -cleanup {
    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 {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 {
    testchmod 0o770 td0/td1
    cleanup
} -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
    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 {
    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







|
<
<
<
<
<
<
<
<







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 (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
    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 {
    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 {
    cleanup
} -body {
    createfile td1 {}
    list [file attributes td1 -hidden 1] [file attributes td1 -hidden] \
	[file attributes td1 -hidden 0]
} -cleanup {
    cleanup







|







|







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 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 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
    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 {
    cleanup
} -body {
    createfile td1 {}
    list [file attributes td1 -system 1] [file attributes td1 -system]
} -cleanup {
    cleanup
} -result {{} 1}







|







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 notInCIenv} -setup {
    cleanup
} -body {
    createfile td1 {}
    list [file attributes td1 -system 1] [file attributes td1 -system]
} -cleanup {
    cleanup
} -result {{} 1}
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
#		    puts $msg
#		}
#	    }
#	}
#    }
#}

# cleanup
cleanup
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







<







1421
1422
1423
1424
1425
1426
1427

1428
1429
1430
1431
1432
1433
1434
#		    puts $msg
#		}
#	    }
#	}
#    }
#}


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
# 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.
#
# 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]]

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)]}]

test winFile-1.1 {TclpGetUserHome} -constraints {win} -body {
    glob ~nosuchuser
} -returnCodes error -result {user "nosuchuser" doesn't exist}
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}






|
|










|







|



|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 © 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 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 {![info exists ::env(CI_USING_WINE)]}]

test winFile-1.1 {TclpGetUserHome} -constraints {win} -body {
    glob ~nosuchuser
} -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}

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
# 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.
#
# 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]]

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






|
|










|







1
2
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 © 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 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
#
# 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.
#
# 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]
}

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)]}]


# several test-cases here expect current directory == [temporaryDirectory]:
cd [temporaryDirectory]

testConstraint exec         [llength [info commands exec]]
testConstraint cat32        [file exists $cat32]








|
|












|
|






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 © 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 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 {![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
    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
    flush $f
    set r [read $f 64]
    catch {close $f}
    set r
} "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"

test winpipe-4.1 {Tcl_WaitPid} {win exec cat32} {







|







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 \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
    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} {
    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 {!($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)]

    }
    set broken {}
    foreach args $args {
	if {$single & 1} {
	    # 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 {$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().
###







|










>
|
|
|
|
|
|
|
|
|
>



|













>
>
>
>
>
>
>



<
<
<
<







314
315
316
317
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 {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 {"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 {"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"
	    }




	}
    }
    return $broken
}

### validate the raw output of BuildCommandLine().
###
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
    {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 \
	[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] \







|







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 {} \
	[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
	[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
} -result {}

test winpipe-8.3 {BuildCommandLine/parse_cmdline pass-thru: check injection on special meta-chars (jointly)} \
-constraints {win exec notWine} -body {
    _testExecArgs 0 \
	[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 \
	[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)} \







|




|








|







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 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 {} \
	[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 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
	    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
} -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 \
	[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
} -result {}


rename _testExecArgs {}

# restore old values for env(TMP) and env(TEMP)








|
















|









|







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 {} {*}$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 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 {} $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
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 }

::tcltest::cleanupTests
# back to original directory:
cd $org_pwd; unset org_pwd
return

# Local Variables:
# mode: tcl
# End:







>








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
# 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.
#
# 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]]

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]






|
|










|


<







1
2
3
4
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 © 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 tcl::test [info patchlevel]]

testConstraint testwinclock [llength [info commands testwinclock]]


# 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
    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} {
    # 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







|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
    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 {
    # 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

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 <[email protected]>

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
# 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.

#
# 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 zipfs [expr {
    [llength [info commands zlib]] && [regexp tcltest [info nameofexecutable]]
}]
testConstraint zipfslib 1

# 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]} {
    ###
    # "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]
    if {[testConstraint zipfslib]} {
        zipfs mount /lib/tcl $tclzip
        set ::tcl_library ${ziproot}lib/tcl/tcl_library
    }

}

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]






|
|
>



>





>

|
<
<
|
|
<
<
<
<
|






|





|
<
<
<
<
<
<
<
|
<
<
|
|
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21


22
23




24
25
26
27
28
29
30
31
32
33
34
35
36
37







38


39
40
41
42
43
44
45
46
47
48
# 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 © 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 {[llength [info commands zipfs]]}]


testConstraint thread [expr {0 == [catch {package require Thread 2.8-}]}]






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 tcl::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]} {







    testConstraint zipfslib 1


    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
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"
test zipfs-0.11 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
    file normalize [zipfs root]
} -result "[zipfs root]"
test zipfs-0.12 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
    file normalize [zipfs root]//bar/baz//qux/../
} -result "[zipfs root]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 list -glob ${ziproot}abc/cp850.*
} -cleanup {
    cd $CWD
} -result "[zipfs root]abc/cp850.enc"
testConstraint zipfsenc [zipfs exists /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







|
|

|
|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















|



|
|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

























87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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 ${ziproot} bar baz
} -result "${ziproot}bar/baz"
test zipfs-0.11 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
    file normalize ${ziproot}
} -result "${ziproot}"
test zipfs-0.12 {zipfs basics: join} -constraints {zipfs zipfslib} -body {
    file normalize ${ziproot}//bar/baz//qux/../
} -result "${ziproot}bar/baz"


























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 $zipfile ${ziproot}abc
    zipfs list -glob ${ziproot}abc/cp850.*
} -cleanup {
    cd $CWD
} -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
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
} -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 list -glob ${ziproot}def/cp850.*
} -cleanup {
    cd $CWD
} -result "[zipfs root]def/cp850.enc"
testConstraint zipfsencbuf [zipfs exists /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







|



















|



|
|







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
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 ${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 $dat def
    zipfs list -glob ${ziproot}def/cp850.*
} -cleanup {
    cd $CWD
} -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
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
} -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







|







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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 ${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
271
272
273
274
275
276
277







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































278
279
280
281
282
283
284
} -body {
    interp eval $safe {
	zipfs mkzip
    }
} -returnCodes error -cleanup {
    interp delete $safe
} -result {not allowed to invoke subcommand mkzip of zipfs}








































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
} -body {
    interp eval $safe {
	zipfs mkzip
    }
} -returnCodes error -cleanup {
    interp delete $safe
} -result {not allowed to invoke subcommand mkzip of 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 mount_data: short data} -constraints zipfs -body {
    zipfs mount_data {} gorp
} -returnCodes error -result {illegal file size}
test zipfs-5.2 {zipfs mount_data: short data} -constraints zipfs -body {
    zipfs mount_data gorpGORPgorp gorp
} -returnCodes error -result {illegal file size}
test zipfs-5.3 {zipfs mount_data: short data} -constraints zipfs -body {
    set data PK\x03\x04.....................................
    append data PK\x01\x02.....................................
    append data PK\x05\x06.....................................
    zipfs mount_data $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-mount_data-$id $id -body {
            list [catch {zipfs mount_data $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-mount_data-$id "zipfs mount_data $id" -body {
            set canon [zipfs mount_data [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 mount_data" "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-mount_data-on-drive "Mount point include drive" -body {
        zipfs mount_data [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-mount_data-on-unc "Mount point include unc" -body {
        zipfs mount_data [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 mount_data [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 mount_data [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 mount_data $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 mount_data $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 mount_data $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 mount_data [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 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
}


::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
# 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.
#
# 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 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
} -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 {






|
|








>
>




















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 © 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 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
    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)
    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} {







|







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)}
    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} {
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
    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}}
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}}
# 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 {







|









|







290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    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 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 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 {
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
    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} {
	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







|







449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
    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} {
	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
482
483
484
485
486
487
488
































489
490
491
492
493
494
495
    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-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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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

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

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.

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












<
<
<
<


|
<
<
<
<
<
<
<
>
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.




This script is very picky about the organization of man pages,
effectively acting as a style enforcer.
The resulting documentation can be found at







    /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
#      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.
# 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."







|







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 © 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
    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 \







<







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_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 [email protected] 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
	@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/'`; \







<
<
<
<
<







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 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
# big5.txt --
#
#	BIG5 to Unicode table (modified)
#
# 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 format:     Format A
#	Date:             11 February 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#
#	Copyright (c) 1991-1994 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.

#
#	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.

#
#	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:
#
|
|
|
|
<

<
<
<
<
<
<
<


|

|
<
<

<
>

<
<
<
<
|
<
<
>

<
<
<
<
<
<
<
<
|
>
>
>
|
>







1
2
3
4

5







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
# 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:             BIG5 to Unicode table (complete)
#	Unicode version:  1.1
#	Table version:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#

#	General notes:
#




# NOTE: this table has been modified to include the 7-bit ASCII


# characters that are allowed in BIG5 files.
#








# 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
#		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.
#
#	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.
#
#
#
#	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 entries are in BIG5 order
#








#	Any comments or problems, contact <John_Jenkins@taligent.com>

#





#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN







|
|
|


|
|
|
|
|
|
|
|
<
<





|
|
|
|
|
|
|



>
>
>
>
>
>
>
>
|
>

>
>
>
>
>







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60


61
62
63
64
65
66
67
68
69
70
71
72
73
74
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.
#
#	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.


#
#	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 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.
#    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
#
#    Name:     cp1250 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp1251 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp1252 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp1253 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp1254 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp1255 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp1256 to Unicode table
#    Unicode version: 2.1
#    Table version: 2.01
#    Table format:  Format A
#    Date:          01/5/99
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp1257 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp1258 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp874 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          02/28/98
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp932 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          04/15/98
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp936 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp949 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
#
#    Name:     cp950 to Unicode table
#    Unicode version: 2.0
#    Table version: 2.01
#    Table format:  Format A
#    Date:          1/7/2000
#
#    Contact:       cpxlat[email protected]
#
#    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, '#')







|







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:       Shawn.Stee[email protected]
#
#    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
# gb2312.txt --
#
#	GB2312 to Unicode table (modified)
#
# 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 GB2312 files.
#




|







1
2
3
4
5
6
7
8
9
10
11
12
# gb2312.txt --
#
#	GB2312 to Unicode table (modified)
#
# 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




#
#	Name:             ISO/IEC 8859-1:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














|
|
>
>


|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (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-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.
#   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

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




#
#	Name:             ISO/IEC 8859-10:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.1
#	Table format:     Format A
#	Date:             1999 October 11
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<















|
>
>


|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
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:    2.0
#	Table format:     Format A
#	Date:             1999 October 11 (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-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
#   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

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 <[email protected]>
#
#	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




#
#	Name:             ISO/IEC 8859-13:1998  to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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.
#





#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<













>
>
>
>
>

|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (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-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:
#		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

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




#
#	Name:             ISO/IEC 8859-14:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Markus Kuhn <mkuhn@acm.org>
#			  Ken Whistler <kenw@sybase.com>
#
#	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.
#





#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<













>
>
>
>
>

|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
12
















13
14
15
16
17
18
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
#			  Ken Whistler <ken@unicode.org>
















#
#	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:
#		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
294
295
296
297
298
299
300
301
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








<
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




#
#	Name:             ISO/IEC 8859-15:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Markus Kuhn <mkuhn@acm.org>
#			  Ken Whistler <kenw@sybase.com>
#
#	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
#





#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<















>
>
>
>
>

|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
12
















13
14
15
16
17
18
19
20
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (header updated: 2015 December 02)
#	Authors:          Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>
#			  Ken Whistler <ken@unicode.org>
















#
#	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:
#		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
296
297
298
299
300
301
302
303
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








<
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




#
#	Name:             ISO/IEC 8859-16:2001 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             2001 July 26
#	Authors:          Markus Kuhn <mkuhn@acm.org>
#
#	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.
#





#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|



<
<
<
<
<
<
<
<
<
<
<
<
<
<












>
>
>
>
>

|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14














15
16
17
18
19
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:    2.0
#	Table format:     Format A
#	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.
#














#	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:
#		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

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




#
#	Name:             ISO 8859-2:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














|
|
>
>


|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (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-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.
#   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

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




#
#	Name:             ISO/IEC 8859-3:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














|
|
>
>


|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (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-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.
#   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

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




#
#	Name:             ISO/IEC 8859-4:1998 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














|
|
>
>


|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (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-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.
#   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

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




#
#	Name:             ISO 8859-5:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














|
|
>
>


|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (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-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.
#   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

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




#
#	Name:             ISO 8859-6:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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).


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<














|
|
|
|
>
>


|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
19
20
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (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-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).
#   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

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




#
#	Name:             ISO 8859-7:1987 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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:1987 is equivalent to ISO-IR-126, ELOT 928,
#	and ECMA 118.

#
#	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
#






#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>

|
|
|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|


|
>














>
>
>
>
>
>

|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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:2003 to Unicode
#	Unicode version:  4.0
#	Table version:    3.0
#	Table format:     Format A
#	Date:             2003-Nov-12 (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 8859-7:2003 characters map into Unicode.
#
#	ISO 8859-7:1987 is equivalent to ISO-IR-126, ELOT 928,
#	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:
#		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
210
211
212
213
214
215
216


217
218
219
220

221
222
223
224
225
226
227
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


0xA6	0x00A6	#	BROKEN BAR
0xA7	0x00A7	#	SECTION SIGN
0xA8	0x00A8	#	DIAERESIS
0xA9	0x00A9	#	COPYRIGHT SIGN

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







>
>




>







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




#
#	Name:             ISO/IEC 8859-8:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.1
#	Table format:     Format A
#	Date:             2000-Jan-03
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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
#          the mapping of 0xAF and adding mappings for LRM and RLM.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















|

>
>


|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
19
20
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:    2.0
#	Table format:     Format A
#	Date:             2000-Jan-03 (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-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
#          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:
#		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
263
264
265
266
267
268
269
270
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








<
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




#
#	Name:             ISO/IEC 8859-9:1999 to Unicode
#	Unicode version:  3.0
#	Table version:    1.0
#	Table format:     Format A
#	Date:             1999 July 27
#	Authors:          Ken Whistler <kenw@sybase.com>
#
#	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.


#
#	Updated versions of this file may be found in:
#		<ftp://ftp.unicode.org/Public/MAPPINGS/>
#
#	Any comments or problems, contact <errat[email protected]>
#	Please note that <errata@unicode.org> is an archival address;
#	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
>
>
>
>



|

|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
















|
|
>
>


|

|
|
<







1
2
3
4
5
6
7
8
9
10
11
















12
13
14
15
16
17
18
19
20
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:    2.0
#	Table format:     Format A
#	Date:             1999 July 27 (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-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.
#   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
299
300
301
302
303
304
305
306
307
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










<
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




#
#	Name:             JIS X 0201 (1976) to Unicode 1.1 Table
#	Unicode version:  1.1
#	Table version:    0.9
#	Table format:     Format A
#	Date:             8 March 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#
#	Copyright (c) 1991-1994 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.
#
#	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 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.
#


#	Any comments or problems, contact <John_Jenkins@taligent.com>

#





#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN
>
>
>
>



|

|
<
<

<
>

<
<
<
<
<
<
<

<
>
>
>
|
|
<
<
>

<
<
<
<
<








|
>
>
>
|

>
>
|
>

>
>
>
>
>







1
2
3
4
5
6
7
8
9
10


11

12
13







14

15
16
17
18
19


20
21





22
23
24
25
26
27
28
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:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#

#	General notes:
#







#

# 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


# VENDORS mapping data.
#





#
#	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
#
#  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.
#
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




#
#	Name:             JIS X 0208 (1990) to Unicode
#	Unicode version:  1.1
#	Table version:    0.9
#	Table format:     Format A
#	Date:             8 March 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#
#	Copyright (c) 1991-1994 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.
#
#	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 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 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
#


#	Any comments or problems, contact <John_Jenkins@taligent.com>

#





#
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
>
>
>
>



|

|
<
<

<
>

<
<
<
<
<
<
<

<
>
>
>
|
|
<
<
>

<
<
<
<






|
|
|
|
|
|
|












|
>
|
>
|

>
>
|
>

>
>
>
>
>







1
2
3
4
5
6
7
8
9
10


11

12
13







14

15
16
17
18
19


20
21




22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#

#	General notes:
#







#

# 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


# VENDORS mapping data.
#




#
#	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 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
#
#  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.
#
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




#
#	Name:             JIS X 0212 (1990) to Unicode
#	Unicode version:  1.1
#	Table version:    0.9
#	Table format:     Format A
#	Date:             8 March 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#
#	Copyright (c) 1991-1994 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.
#
#	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 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 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 <[email protected]>
#
#	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.
#

















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
>
>
>
>



|

|
<
<

<
>

<
<
<
<
<
<
<

<
>
>
>
|
|
<
<
>

<
<
<
<





|
|
|
|
|
|
|












<
<
<
<
<
<















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10


11

12
13







14

15
16
17
18
19


20
21




22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45






46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#

#	General notes:
#







#

# 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


# VENDORS mapping data.
#




#
#	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 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
#






#	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




#
#	Name:             Shift-JIS to Unicode
#	Unicode version:  1.1
#	Table version:    0.9
#	Table format:     Format A
#	Date:             8 March 1994
#	Authors:          Glenn Adams <[email protected]>
#                     John H. Jenkins <[email protected]>
#
#	Copyright (c) 1991-1994 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.
#
#	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 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 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
#


#	Any comments or problems, contact <John_Jenkins@taligent.com>

#





#
0x20	0x0020	# SPACE
0x21	0x0021	# EXCLAMATION MARK
0x22	0x0022	# QUOTATION MARK
0x23	0x0023	# NUMBER SIGN
0x24	0x0024	# DOLLAR SIGN
0x25	0x0025	# PERCENT SIGN
>
>
>
>



|

|
<
<

<
>

<
<
<
<
<
<
<

<
>
>
>
|
|
<
<
>

<
<
<
<





|
|
|
|
|
|
|










|
>
|
>
|

>
>
|
>

>
>
>
>
>







1
2
3
4
5
6
7
8
9
10


11

12
13







14

15
16
17
18
19


20
21




22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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:    2.0
#	Table format:     Format A
#	Date:             2011 October 14 (header updated: 2015 December 02)


#

#	General notes:
#







#

# 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


# VENDORS mapping data.
#




#
#	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 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.
#
#  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.
#
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
	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);
	return 1;
    }

    fp = fopen(argv[argc - 1], "r");
    if (fp == NULL) {
        perror(argv[argc - 1]);
	return 1;







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
	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 007F\n", stderr);
	return 1;
    }

    fp = fopen(argv[argc - 1], "r");
    if (fp == NULL) {
        perror(argv[argc - 1]);
	return 1;
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
	    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;
		}
	    }
	}
    }

    printf("# Encoding file: %s, %s-byte\n", argv[argc - 1], typeString[type]);

    if (fallbackChar == '\0') {







<
|
|
<







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) {

	    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') {

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)
##
##  [email protected]    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
# 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
#
# 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} {













|







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 © 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
# 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 <[email protected]>
#
# 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 --
    #






|
|







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 © 1998-1999 Scriptics Corporation.
# Copyright © 2007 Daniel A. Steffen <[email protected]>
#
# 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

proc genStubs::rewriteFile {file text} {
    if {![file exists $file]} {
	puts stderr "Cannot find file: $file"
	return
    }
    set in [open ${file} r]

    set out [open ${file}.new w]
    fconfigure $out -translation lf

    while {![eof $in]} {
	set line [gets $in]
	if {[string match "*!BEGIN!*" $line]} {
	    break
	}
	puts $out $line







>

|







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 -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
			# 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] /*\
				Dummy entry for stubs table backwards\
				compatibility */\n"
		    }
		    if {$slot($plat)} {
			append temp [$slotProc $name $stubs($name,$plat,$i) $i]
		    } elseif {$onAll} {
			eval {append temp} $skipString
		    }
		}







|

|







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 "# if TCL_MAJOR_VERSION < 9\n[string range $temp 0 end-1] /*\
				Dummy entry for stubs table backwards\
				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
	    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} {
		set root 0
		break
	    }
	}
    }

    append text "\n"







|







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 {$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
	puts stderr "usage: $argv0 outDir declFile ?declFile...?"
	exit 1
    }

    set outDir [lindex $argv 0]

    foreach file [lrange $argv 1 end] {
	source $file
    }

    foreach name [lsort [array names interfaces]] {
	puts "Emitting $name"
	emitHeader $name
    }








|







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 -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
# 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} {
    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







|










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 {[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
# 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.
#
# 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.






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 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 © 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.

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
#
#	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.
# 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
	    } else {
		file attributes [file join $d2 $ftail] -readonly 1
	    }
	}
    }

    if {$::tcl_platform(platform) eq {unix}} {
	file attributes $d2 -permissions 0755
    } else {
	file attributes $d2 -readonly 1
    }

}

copyDir [file normalize [lindex $argv 0]] [file normalize [lindex $argv 1]]







|



















|







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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 © 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 0o644
	    } else {
		file attributes [file join $d2 $ftail] -readonly 1
	    }
	}
    }

    if {$::tcl_platform(platform) eq {unix}} {
	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
#!/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.
# 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]} {












|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh
#\
exec tclsh "$0" ${1+"$@"}

#----------------------------------------------------------------------
#
# installVfs.tcl --
#
#        This file wraps the /library file system around a binary
#
#----------------------------------------------------------------------
#
# 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]} {

Changes to tools/loadICU.tcl.

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.
# 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.








|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#	None.
#
# Side effects:
#	Creates the message catalogs.
#
#----------------------------------------------------------------------
#
# 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
# makeHeader.tcl --
#
#	This script generates embeddable C source (in a .h file) from a .tcl
#	script.
#
# Copyright (c) 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

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]
    }

    ####################################################################
    #
    # compactLeadingSpaces --
    #	Converts the leading whitespace on a line into a more compact form.
    #





|




|
















|







1
2
3
4
5
6
7
8
9
10
11
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 © 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-

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 {[^\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
    #
    # updateTemplateFile --
    #	Rewrites a template file with the lines of the given script.
    #
    proc updateTemplateFile {headerFile scriptLines} {
	set f [open $headerFile "r+"]
	try {

	    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







>







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
# 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]

namespace eval ::tcl::clock {
    ::msgcat::mcmset en_US_roman {
	LOCALE_ERAS {
	    {-62164627200 {} 0}
	    {-59008867200 c 100}
	    {-55853107200 cc 200}






|







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 -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}

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.

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    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
	          }
	      }
    }

    if {$::tcl_platform(platform) eq {unix}} {
      	file attributes $d2 -permissions 0755
    } else {
	      file attributes $d2 -readonly 1
    }
}

if {[llength $argv] < 3} {
    puts "Usage: VFS_ROOT TCLSRC_ROOT PLATFORM"







|







|







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    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 0o644
      	    } else {
            		file attributes [file join $d2 $ftail] -readonly 1
	          }
	      }
    }

    if {$::tcl_platform(platform) eq {unix}} {
      	file attributes $d2 -permissions 0o755
    } else {
	      file attributes $d2 -readonly 1
    }
}

if {[llength $argv] < 3} {
    puts "Usage: VFS_ROOT TCLSRC_ROOT PLATFORM"

Changes to tools/mkdepend.tcl.

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
#
# 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.
#




|







1
2
3
4
5
6
7
8
9
10
11
12
#==============================================================================
#
# mkdepend : generate dependency information from C/C++ files
#
# 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.
#
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
}

# addSearchPath --
#
#	Adds a new set of path and replacement string to the global list.
#
# Arguments:
#	newPathInfo	comma seperated path and replacement string
#
# Results:
#	None.

proc addSearchPath {newPathInfo} {
    global srcPathList srcPathReplaceList








|







248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
}

# addSearchPath --
#
#	Adds a new set of path and replacement string to the global list.
#
# Arguments:
#	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

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.
    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}







|







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 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
# 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.

proc readInputFile {} {
    global inFileName
    global lineArray

    set fileId [open $inFileName r]







|







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 © 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

    close $fileId
    return $i
}

#
# strings with embedded @'s are truncated
# unpreceeded @'s are replaced by {}
#
proc removeAts {ls} {
    set len [llength $ls]
    set newLs {}
    foreach item $ls {
	regsub @.* $item "" newItem
	lappend newLs $newItem







|







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

    close $fileId
    return $i
}

#
# strings with embedded @'s are truncated
# unpreceded @'s are replaced by {}
#
proc removeAts {ls} {
    set len [llength $ls]
    set newLs {}
    foreach item $ls {
	regsub @.* $item "" newItem
	lappend newLs $newItem
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 "#"
    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\} \{"







|







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 © 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
    }

    # perform mapping if '=' flag exists

    set noBraces 0
    if {[regexp {=|>} $flags] == 1} {
	regsub -all {_} $currentLine {\\ } currentLine
	regsub -all {A} $currentLine {\\007} currentLine
	regsub -all {B} $currentLine {\\b} currentLine
	regsub -all {E} $currentLine {\\033} 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]
	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]
    }







|

|






|







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 {\\x07} currentLine
	regsub -all {B} $currentLine {\\b} 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 {\\\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
# 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.
#
# Copyright (c) 2012-2018 Donal K. Fellows
# Copyright (c) 2013 Andreas Kupries
# Copyright (c) 2017 Gerald Lester
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

::namespace eval ::oo {
    ::namespace path {}

    #
    # Commands that are made available to objects by default.
    #
    namespace eval Helpers {
	::namespace path {}

	# ------------------------------------------------------------------
	#
	# callback, mymethod --
	#
	#	Create a script prefix that calls a method on the current
	#	object. Same operation, two names.






|
|
|











|







1
2
3
4
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.
#
# 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 {}

	# ------------------------------------------------------------------
	#
	# 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
	    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} \
			"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 \







|







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 {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
	    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
	}
	objdefine $class ::oo::objdefine::mixin -append $delegate
    }

    # ----------------------------------------------------------------------
    #
    # UpdateClassDelegatesAfterClone --
    #
    #	Support code that is like [MixinClassDelegates] except for when a







|

|







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 -appendifnew $d
	}
	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
    #
    # 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 \
		{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
    }

    # ----------------------------------------------------------------------
    #







|









|







191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    #
    # Note that the ::oo::define namespace is semi-public and a bit weird
    # anyway, so we don't regard the namespace path as being under control:
    # fully qualified names are used for everything.
    #
    # ----------------------------------------------------------------------

    proc define::classmethod {name args} {
        # Create the method on the class if the caller gave arguments and body
        ::set argc [::llength [::info level 0]]
        ::if {$argc == 3} {
            ::return -code error -errorcode {TCL WRONGARGS} [::format \
		{wrong # args: should be "%s name ?args body?"} \
                [::lindex [::info level 0] 0]]
        }
        ::set cls [::uplevel 1 self]
        ::if {$argc == 4} {
            ::oo::define [::oo::DelegateName $cls] method $name {*}$args
        }
        # Make the connection by forwarding
        ::tailcall forward $name myclass $name
    }

    # ----------------------------------------------------------------------
    #
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
	#
	#	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"
	}

	# ------------------------------------------------------------------
	#
	# 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"
	}

	# ------------------------------------------------------------------
	#
	# 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 {
	    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 {
	    set my [namespace which my]
	    set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
	    tailcall my Set $args
	}
	method -append 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 -clear {} {tailcall my Set {}}
	method -prepend 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 {
	    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} {
	    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
	export -set -append -clear -prepend -remove
	unexport unknown 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} {
	# 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]







|
|











|
|












|












|




|





>
>
>
>
>
>
>
>
>
>
>
|
|





|










|









|
<
|

















|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 -unexport {} {
	    return -code error -errorcode {TCL OO ABSTRACT_SLOT} "unimplemented"
	}

	# ------------------------------------------------------------------
	#
	# Slot Set --
	#
	#	Basic slot setter. Sets the contents of the slot.  Particular
	#	slots must provide concrete non-erroring implementation.
	#
	# ------------------------------------------------------------------

	method Set -unexport list {
	    return -code error -errorcode {TCL OO ABSTRACT_SLOT} "unimplemented"
	}

	# ------------------------------------------------------------------
	#
	# Slot Resolve --
	#
	#	Helper that lets a slot convert a list of arguments of a
	#	particular type to their canonical forms. Defaults to doing
	#	nothing (suitable for simple strings).
	#
	# ------------------------------------------------------------------

	method Resolve -unexport list {
	    return $list
	}

	# ------------------------------------------------------------------
	#
	# Slot -set, -append, -clear, --default-operation --
	#
	#	Standard public slot operations. If a slot can't figure out
	#	what method to call directly, it uses --default-operation.
	#
	# ------------------------------------------------------------------

	method -set -export args {
	    set my [namespace which my]
	    set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
	    tailcall my Set $args
	}
	method -append -export args {
	    set my [namespace which my]
	    set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
	    set current [uplevel 1 [list $my Get]]
	    tailcall my Set [list {*}$current {*}$args]
	}
	method -appendifnew -export args {
	    set my [namespace which my]
	    set current [uplevel 1 [list $my Get]]
	    foreach a $args {
		set a [uplevel 1 [list $my Resolve $a]]
		if {$a ni $current} {
		    lappend current $a
		}
	    }
	    tailcall my Set $current
	}
	method -clear -export {} {tailcall my Set {}}
	method -prepend -export args {
	    set my [namespace which my]
	    set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
	    set current [uplevel 1 [list $my Get]]
	    tailcall my Set [list {*}$args {*}$current]
	}
	method -remove -export args {
	    set my [namespace which my]
	    set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
	    set current [uplevel 1 [list $my Get]]
	    tailcall my Set [lmap val $current {
		if {$val in $args} continue else {set val}
	    }]
	}

	# Default handling
	forward --default-operation my -append
	method unknown -unexport {args} {
	    set def --default-operation
	    if {[llength $args] == 0} {
		tailcall my $def
	    } elseif {![string match -* [lindex $args 0]]} {
		tailcall my $def {*}$args
	    }
	    next {*}$args
	}

	# Hide destroy

	unexport destroy
    }

    # Set the default operation differently for these slots
    objdefine define::superclass forward --default-operation my -set
    objdefine define::mixin forward --default-operation my -set
    objdefine objdefine::mixin forward --default-operation my -set

    # ----------------------------------------------------------------------
    #
    # oo::object <cloned> --
    #
    #	Handler for cloning objects that clones basic bits (only!) of the
    #	object's namespace. Non-procedures, traces, sub-namespaces, etc. need
    #	more complex (and class-specific) handling.
    #
    # ----------------------------------------------------------------------

    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
    #
    # oo::class <cloned> --
    #
    #	Handler for cloning classes, which fixes up the delegates.
    #
    # ----------------------------------------------------------------------

    define class method <cloned> {originObject} {
	next $originObject
	# Rebuild the class inheritance delegation class
	::oo::UpdateClassDelegatesAfterClone $originObject [self]
    }

    # ----------------------------------------------------------------------
    #







|







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> -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
	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} \
			    "may not destroy a singleton object"
		    }
		    method <cloned> {originObject} {
			::return -code error -errorcode {TCLOO SINGLETON} \
			    "may not clone a singleton object"
		    }
		}
	    }
	    return $object
	}
    }







|


|
|







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 {TCL OO SINGLETON} \
			    "may not destroy a singleton object"
		    }
		    method <cloned> -unexport {originObject} {
			::return -code error -errorcode {TCL OO SINGLETON} \
			    "may not clone a singleton object"
		    }
		}
	    }
	    return $object
	}
    }
443
444
445
446
447
448
449












































































































































































































































































































































450
451
452
453
454
455
456
    #
    # ----------------------------------------------------------------------

    class create abstract {
	superclass class
	unexport create createWithNamespace new
    }












































































































































































































































































































































}

# Local Variables:
# mode: tcl
# c-basic-offset: 4
# fill-column: 78
# End:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    #
    # ----------------------------------------------------------------------

    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
    #
    #	Those are all slot implementations that provide access to the C layer
    #	of property support (i.e., very fast cached lookup of property names).
    #
    # ----------------------------------------------------------------------

    ::namespace eval configuresupport {
	namespace path ::tcl

	# ------------------------------------------------------------------
	#
	# oo::configuresupport --
	#
	#	A metaclass that is used to make classes that can be configured.
	#
	# ------------------------------------------------------------------

	proc PropertyImpl {readslot writeslot args} {
	    for {set i 0} {$i < [llength $args]} {incr i} {
		# Parse the property name
		set prop [lindex $args $i]
		if {[string match "-*" $prop]} {
		    return -code error -level 2 \
			-errorcode {TCL OO PROPERTY_FORMAT} \
			"bad property name \"$prop\": must not begin with -"
		}
		if {$prop ne [list $prop]} {
		    return -code error -level 2 \
			-errorcode {TCL OO PROPERTY_FORMAT} \
			"bad property name \"$prop\": must be a simple word"
		}
		if {[string first "::" $prop] != -1} {
		    return -code error -level 2 \
			-errorcode {TCL OO PROPERTY_FORMAT} \
			"bad property name \"$prop\": must not contain namespace separators"
		}
		if {[string match {*[()]*} $prop]} {
		    return -code error -level 2 \
			-errorcode {TCL OO PROPERTY_FORMAT} \
			"bad property name \"$prop\": must not contain parentheses"
		}
		set realprop [string cat "-" $prop]
		set getter [format {::set [my varname %s]} $prop]
		set setter [format {::set [my varname %s] $value} $prop]
		set kind readwrite

		# Parse the extra options
		while {[set next [lindex $args [expr {$i + 1}]]
			string match "-*" $next]} {
		    set arg [lindex $args [incr i 2]]
		    switch [prefix match -error [list -level 2 -errorcode \
			    [list TCL LOOKUP INDEX option $next]] {-get -kind -set} $next] {
			-get {
			    if {$i >= [llength $args]} {
				return -code error -level 2 \
				    -errorcode {TCL WRONGARGS} \
				    "missing body to go with -get option"
			    }
			    set getter $arg
			}
			-set {
			    if {$i >= [llength $args]} {
				return -code error -level 2 \
				    -errorcode {TCL WRONGARGS} \
				    "missing body to go with -set option"
			    }
			    set setter $arg
			}
			-kind {
			    if {$i >= [llength $args]} {
				return -code error -level 2\
				    -errorcode {TCL WRONGARGS} \
				    "missing kind value to go with -kind option"
			    }
			    set kind [prefix match -message "kind" -error [list \
				    -level 2 \
				    -errorcode [list TCL LOOKUP INDEX kind $arg]] {
				readable readwrite writable
			    } $arg]
			}
		    }
		}

		# Install the option
		set reader <ReadProp$realprop>
		set writer <WriteProp$realprop>
		switch $kind {
		    readable {
			uplevel 2 [list $readslot -append $realprop]
			uplevel 2 [list $writeslot -remove $realprop]
			uplevel 2 [list method $reader -unexport {} $getter]
		    }
		    writable {
			uplevel 2 [list $readslot -remove $realprop]
			uplevel 2 [list $writeslot -append $realprop]
			uplevel 2 [list method $writer -unexport {value} $setter]
		    }
		    readwrite {
			uplevel 2 [list $readslot -append $realprop]
			uplevel 2 [list $writeslot -append $realprop]
			uplevel 2 [list method $reader -unexport {} $getter]
			uplevel 2 [list method $writer -unexport {value} $setter]
		    }
		}
	    }
	}

	# ------------------------------------------------------------------
	#
	# oo::configuresupport::configurableclass,
	# oo::configuresupport::configurableobject --
	#
	#	Namespaces used as implementation vectors for oo::define and
	#	oo::objdefine when the class/instance is configurable.
	#
	# ------------------------------------------------------------------

	namespace eval configurableclass {
	    ::proc property args {
		::oo::configuresupport::PropertyImpl \
		    ::oo::configuresupport::readableproperties \
		    ::oo::configuresupport::writableproperties {*}$args
	    }
	    # Plural alias just in case; deliberately NOT documented!
	    ::proc properties args {::tailcall property {*}$args}
	    ::namespace path ::oo::define
	    ::namespace export property
	}

	namespace eval configurableobject {
	    ::proc property args {
		::oo::configuresupport::PropertyImpl \
		    ::oo::configuresupport::objreadableproperties \
		    ::oo::configuresupport::objwritableproperties {*}$args
	    }
	    # Plural alias just in case; deliberately NOT documented!
	    ::proc properties args {::tailcall property {*}$args}
	    ::namespace path ::oo::objdefine
	    ::namespace export property
	}

	# ------------------------------------------------------------------
	#
	# oo::configuresupport::ReadAll --
	#
	#	The implementation of [$o configure] with no extra arguments.
	#
	# ------------------------------------------------------------------

	proc ReadAll {object my} {
	    set result {}
	    foreach prop [info object properties $object -all -readable] {
		try {
		    dict set result $prop [$my <ReadProp$prop>]
		} on error {msg opt} {
		    dict set opt -level 2
		    return -options $opt $msg
		} on return {msg opt} {
		    dict incr opt -level 2
		    return -options $opt $msg
		} on break {} {
		    return -code error -level 2 -errorcode {TCL OO SHENANIGANS} \
			"property getter for $prop did a break"
		} on continue {} {
		    return -code error -level 2 -errorcode {TCL OO SHENANIGANS} \
			"property getter for $prop did a continue"
		}
	    }
	    return $result
	}

	# ------------------------------------------------------------------
	#
	# oo::configuresupport::ReadOne --
	#
	#	The implementation of [$o configure -prop] with that single
	#	extra argument.
	#
	# ------------------------------------------------------------------

	proc ReadOne {object my propertyName} {
	    set props [info object properties $object -all -readable]
	    try {
		set prop [prefix match -message "property" $props $propertyName]
	    } on error {msg} {
		catch {
		    set wps [info object properties $object -all -writable]
		    set wprop [prefix match $wps $propertyName]
		    set msg "property \"$wprop\" is write only"
		}
		return -code error -level 2 -errorcode [list \
			TCL LOOKUP INDEX property $propertyName] $msg
	    }
	    try {
		set value [$my <ReadProp$prop>]
	    } on error {msg opt} {
		dict set opt -level 2
		return -options $opt $msg
	    } on return {msg opt} {
		dict incr opt -level 2
		return -options $opt $msg
	    } on break {} {
		return -code error -level 2 -errorcode {TCL OO SHENANIGANS} \
		    "property getter for $prop did a break"
	    } on continue {} {
		return -code error -level 2 -errorcode {TCL OO SHENANIGANS} \
		    "property getter for $prop did a continue"
	    }
	    return $value
	}

	# ------------------------------------------------------------------
	#
	# oo::configuresupport::WriteMany --
	#
	#	The implementation of [$o configure -prop val ?-prop val...?].
	#
	# ------------------------------------------------------------------

	proc WriteMany {object my setterMap} {
	    set props [info object properties $object -all -writable]
	    foreach {prop value} $setterMap {
		try {
		    set prop [prefix match -message "property" $props $prop]
		} on error {msg} {
		    catch {
			set rps [info object properties $object -all -readable]
			set rprop [prefix match $rps $prop]
			set msg "property \"$rprop\" is read only"
		    }
		    return -code error -level 2 -errorcode [list \
			    TCL LOOKUP INDEX property $prop] $msg
		}
		try {
		    $my <WriteProp$prop> $value
		} on error {msg opt} {
		    dict set opt -level 2
		    return -options $opt $msg
		} on return {msg opt} {
		    dict incr opt -level 2
		    return -options $opt $msg
		} on break {} {
		    return -code error -level 2 -errorcode {TCL OO SHENANIGANS} \
			"property setter for $prop did a break"
		} on continue {} {
		    return -code error -level 2 -errorcode {TCL OO SHENANIGANS} \
			"property setter for $prop did a continue"
		}
	    }
	    return
	}

	# ------------------------------------------------------------------
	#
	# oo::configuresupport::configurable --
	#
	#	The class that contains the implementation of the actual
	#	'configure' method (mixed into actually configurable classes).
	#	Great care needs to be taken in these methods as they are
	#	potentially used in classes where the current namespace is set
	#	up very strangely.
	#
	# ------------------------------------------------------------------

	::oo::class create configurable {
	    private variable my
	    #
	    # configure --
	    #	Method for providing client access to the property mechanism.
	    #	Has a user-facing API similar to that of [chan configure].
	    #
	    method configure -export args {
		::if {![::info exists my]} {
		    ::set my [::namespace which my]
		}
		::if {[::llength $args] == 0} {
		    # Read all properties
		    ::oo::configuresupport::ReadAll [self] $my
		} elseif {[::llength $args] == 1} {
		    # Read a single property
		    ::oo::configuresupport::ReadOne [self] $my \
			[::lindex $args 0]
		} elseif {[::llength $args] % 2 == 0} {
		    # Set properties, one or several
		    ::oo::configuresupport::WriteMany [self] $my $args
		} else {
		    # Invalid call
		    ::return -code error -errorcode {TCL WRONGARGS} \
			[::format {wrong # args: should be "%s"} \
			    "[self] configure ?-option value ...?"]
		}
	    }

	    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
#----------------------------------------------------------------------
#
# tclZIC.tcl --
#
#	Take the time zone data source files from Arthur Olson's
#	repository at elsie.nci.nih.gov, and prepare time zone
#	information files for Tcl.
#
# Usage:
#	tclsh tclZIC.tcl inputDir outputDir
#
# Parameters:
#	inputDir - Directory (e.g., tzdata2003e) 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.
# 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.






|






|














|







1
2
3
4
5
6
7
8
9
10
11
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 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., 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 © 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.

1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
	    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
	puts $f "\# created by $::argv0 - do not edit"
	puts $f ""
	puts $f [list set TZData(:$zoneName) $data]
	close $f
    }

    return







|







1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
	    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 -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
	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
	puts $f "\# created by $::argv0 - do not edit"
	puts $f $ifCmd
	puts $f $setCmd
	close $f
    }

    return







|







1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
	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 -encoding utf-8
	puts $f "\# created by $::argv0 - do not edit"
	puts $f $ifCmd
	puts $f $setCmd
	close $f
    }

    return

Changes to tools/tcltk-man2html-utils.tcl.

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

set ::manual(report-level) 1

proc manerror {msg} {
    global manual
    set name {}
    set subj {}





|
|







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 © 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
##
## templating
##
proc indexfile {} {
    if {[info exists ::TARGET] && $::TARGET eq "devsite"} {
	return "index.tml"
    } else {
	return "contents.htm"
    }
}

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]]"
    # 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 "[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"
    foreach {uptitle url} $args {
	set header "<a href=\"$url\">$uptitle</a> <small>&gt;</small> $header"
    }
    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>"
	    }
	}
	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 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;"

    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" \




	    {\(+-}	"&#177;" \



	    {\(co}	"&copy;" \
	    {\(em}	"&#8212;" \

	    {\(en}	"&#8211;" \
	    {\(fm}	"&#8242;" \






	    {\(mc}	"&#181;" \












	    {\(mu}	"&#215;" \









	    {\(mi}	"&#8722;" \








	    {\(->}	"<font size=\"+1\">&#8594;</font>" \

	    {\fP}	{\fR} \
	    {\.}	. \
	    {\(bu}	"&#8226;" \

	    ]
    # 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 {prefix suffix} {
	    o ring / slash : uml ' acute ^ circ ` grave
	} {
	    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
	# B R
	if {[regsub {^([^\\]*)\\fB([^\\]*)\\fR(.*)$} $text \
		{\1<B>\2</B>\3} text]} continue
	# B I
	if {[regsub {^([^\\]*)\\fB([^\\]*)\\fI(.*)$} $text \
		{\1<B>\2</B>\\fI\3} text]} continue
	# I R
	if {[regsub {^([^\\]*)\\fI([^\\]*)\\fR(.*)$} $text \
		{\1<I>\2</I>\3} text]} continue
	# I B
	if {[regsub {^([^\\]*)\\fI([^\\]*)\\fB(.*)$} $text \
		{\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 \







|





|
|










|












<
<
<
<






|



|







|


|















>
>
>
>















|
|












>
>
>
>
|
>
>
>

|
>
|
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>


|
>


|

|


>











|


|


|


|


|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76




77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
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 "index.html"
    }
}

proc copyright {copyright {level {}}} {
    # We don't actually generate a separate copyright page anymore
    #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 "[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 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 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>"
    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>"
	    }
	}
	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 "&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;" \
	    {\(Ye}	"&yen;" \
	    {\(bb}	"&brvbar;" \
	    {\(sc}	"&sect;" \
	    {\(ad}	"&die;" \
	    {\(co}	"&copy;" \
	    {\(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}	"&bull;" \
	    {\*(qo}	"&ocirc;" \
	    ]
    # This might make a few invalid mappings, but we don't use them
    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 ~ 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
	# B R
	if {[regsub {^([^\\]*)\\fB([^\\]*)\\fR(.*)$} $text \
		{\1<b>\2</b>\3} text]} continue
	# B I
	if {[regsub {^([^\\]*)\\fB([^\\]*)\\fI(.*)$} $text \
		{\1<b>\2</b>\\fI\3} text]} continue
	# I R
	if {[regsub {^([^\\]*)\\fI([^\\]*)\\fR(.*)$} $text \
		{\1<i>\2</i>\3} text]} continue
	# I B
	if {[regsub {^([^\\]*)\\fI([^\\]*)\\fB(.*)$} $text \
		{\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
##
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>"
}

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" ||







|
|







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).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
    # 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>"
    lappend manual(section-toc) \
	"<DD><A HREF=\"$manual(name).htm#$here\" NAME=\"$there\">$switch, $name, $class</A>"
    return "<A NAME=\"$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)
	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>"
}

##
## 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>
    backup-text 1
    set para {}
    while {[next-op-is .OP rest]} {
	switch -exact -- [llength $rest] {
	    3 {
		lassign $rest switch name class
	    }







|

|
|





|






|
|








|
|







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).html#$here\">$switch, $name, $class</a>"
    lappend manual(section-toc) \
	"<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)
	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.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>
    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
	}
	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>

	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 {







|
|
|
|
|







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>

	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
		    }
		} else {
		    man-puts $line
		}
	    }
	}
    }
    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
	    output-IP-list .RS .IP $rest2
	}
	if {[match-text .RE .sp .RS @rest .RE]} {
	    man-puts <P>$rest
	    return
	}
	if {[next-op-is .RE rest]} {
	    return
	}
    }
    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







|
|










|



|






|







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>
}

##
## 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
	    output-IP-list .RS .IP $rest2
	}
	if {[match-text .RE .sp .RS @rest .RE]} {
	    man-puts <p>$rest
	    return
	}
	if {[next-op-is .RE rest]} {
	    return
	}
    }
    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
		    output-directive $line
		}
	    }
	} else {
	    man-puts $line
	}
    }
    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>
	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>"
		    continue
		}
		if {$code in {.br .DS .RS}} {
		    output-directive $line
		} else {
		    backup-text 1
		    break
		}
	    } else {
		man-puts $line
	    }
	}
	man-puts </DL>
    } else {
	# labelled list, make contents
	if {$context ne ".SH" && $context ne ".SS"} {
	    man-puts <P>
	}
	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>"
	    }
	}
	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>"
			} elseif {[regexp {^\[([\da-f]+)\]$} $rest -> 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>"
			} else {
			    man-puts "$para<DT>[long-toc $rest]<DD>"
			}
		    }
		    .sp - .br - .DS - .CS {
			output-directive $line
		    }
		    .RS {
			if {[match-text .RS]} {







|










|





|












|



|

|
|


|
|
|
|
|


















|

|

|
|
|

|







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>
}

##
## 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>
	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>"
		    continue
		}
		if {$code in {.br .DS .RS}} {
		    output-directive $line
		} else {
		    backup-text 1
		    break
		}
	    } else {
		man-puts $line
	    }
	}
	man-puts </dl>
    } else {
	# labelled list, make contents
	if {$context ne ".SH" && $context ne ".SS"} {
	    man-puts <p>
	}
	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 {"&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>"
			} elseif {[regexp {^\[([\da-f]+)\]$} $rest -> value]} {
			    man-puts "$para<li value=\"$value\">"
			} elseif {[regexp {^\(?([\da-f]+)\)$} $rest -> value]} {
			    man-puts "$para<li value=\"$value\">"
			} elseif {"&bull;" eq $rest} {
			    man-puts "$para<li>"
			} else {
			    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
			} 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>"
			    incr accept_RE 1
			} elseif {[match-text @rest .RE]} {
			    # gad, this is getting ridiculous
			    if {!$accept_RE} {
				man-puts "$enddl<P>$rest$dl"
				backup-text 1
				set para {}
				break
			    }
			    man-puts "<P>$rest"
			    incr accept_RE -1
			} elseif {$accept_RE} {
			    output-directive $line
			} else {
			    backup-text 1
			    break
			}







|
|




|




|







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>"
			    incr accept_RE 1
			} elseif {[match-text @rest .RE]} {
			    # gad, this is getting ridiculous
			    if {!$accept_RE} {
				man-puts "$enddl<p>$rest$dl"
				backup-text 1
				set para {}
				break
			    }
			    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
			backup-text 1
			break
		    }
		}
	    } else {
		man-puts $line
	    }
	    set para <P>
	}
	man-puts "$para$enddl"
	lappend manual(section-toc) $enddl
	if {$accept_RE} {
	    manerror "missing .RE in output-IP-list"
	}
    }







|







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>
	}
	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
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>"
    # 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
}

##
## build a cross-reference link if appropriate
##
proc cross-reference {ref} {
    global manual remap_link_target







|









|







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>"
    # 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).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
	}
    } 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>"
    } 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)







|







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>"
    } 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
	    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>"
	    }
	}
	if {$lref in {end}} {
	    # no good place to send this tcl token?
	}
	return $ref
    }







|







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).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
    ## 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>"
	}
	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>"
	}
	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>"
	}
	puts stderr "multiple cross reference to $ref in $manref from $manual(wing-file)/$mantail"
	return $ref
    }
    ##
    ## exceptions, sigh, to the rule
    ##







|





|



|







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.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.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.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
	&& $lref in $exclude_refs_map($mantail)
    } {
	return $ref
    }
    ##
    ## return the cross reference
    ##
    return "<A HREF=\"../$manref.htm\">$ref</A>"
}

##
## reference generation errors
##
proc reference-error {msg text} {
    global manual







|







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.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
    global manual
    set result ""

    while 1 {
	##
	## we identify cross references by:
	##     ``quotation''
	##    <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>}
	    quote      {``}	end-quote  {''}
	    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}







|










|

|







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>
	##    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>}
	    quote      {``}	end-quote  {''}
	    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
		    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 {

			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
		    }







>
|
>







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}]]
			}
			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
		    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 {

			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>
			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 {

		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]

		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]

		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>"
		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>
	}
	.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>"
	    } else {
		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>
		    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>
			    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>
			    }
			    man-puts $spaces$more<BR>
			    if {$manual(wing-file) in {TclLib TkLib}} {
				lappend manual(section-toc) <DD>$more
			    }
			}
		    }
		    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>(.*)\([13n]\)</B>$} $cr all name]} {
				set cr <B>$name</B>
			    }
			    lappend nmore $cr
			}
			man-puts [join $nmore {, }]
		    }
		    return
		}







>
|
|
>




|
|















>
|
|
>









>
|
>






>
|
>


|




















|









|

|



















|


















|












|

|

|



|

















|
|

|
|







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}]]
			}
			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>
			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}]]
		}
		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}]]
		}
		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}]]
		}
		regexp -indices -start $off {http://[\w/.-]+} $text range
		set url [string range $text {*}$range]
		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>
	}
	.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>"
	    } else {
		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>
		    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>
			    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>
			    }
			    man-puts $spaces$more<br>
			    if {$manual(wing-file) in {TclLib TkLib}} {
				lappend manual(section-toc) <dd>$more
			    }
			}
		    }
		    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>(.*)\([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
			    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]
			    set initial [string toupper [string index $key 0]]
			    lappend keys "<A href=\"../Keywords/$initial.htm\#$key\">$key</A>"
			}
			man-puts [join $keys {, }]
		    }
		    return
		}
	    }
	    if {[next-op-is .IP rest]} {







|

|







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).html]
			    set initial [string toupper [string index $key 0]]
			    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
		    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>
	    foreach optionpair [lsort -dictionary -index 0 $optslist] {
		lassign $optionpair option targetPage
		man-puts "<DT><B>[std-option-toc $option $targetPage]</B>"
	    }
	    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>
	}
	.RS {
	    output-RS-list
	    return
	}
	.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>
	    } elseif {[match-text .fi @ul1 @ul2 .nf @stuff .DE]} {
		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>
	    } 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>
		}
	    } elseif {[match-text .RS @more .RE .fi]} {
		man-puts <DL><DD>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		}
		man-puts </DL>
	    } elseif {[match-text .RS @more .RS @more2 .RE .RE .fi]} {
		man-puts <DL><DD>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		}
		man-puts <DL><DD>
		foreach more2 [split $more2 \n] {
		    man-puts $more2<BR>
		}
		man-puts </DL></DL>
	    } elseif {[match-text .RS @more .RS @more2 .RE @more3 .RE .fi]} {
		man-puts <DL><DD>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		}
		man-puts <DL><DD>
		foreach more2 [split $more2 \n] {
		    man-puts $more2<BR>
		}
		man-puts </DL><DD>
		foreach more3 [split $more3 \n] {
		    man-puts $more3<BR>
		}
		man-puts </DL>
	    } elseif {[match-text .sp .RS @more .RS @more2 .sp .RE .RE .fi]} {
		man-puts <P><DL><DD>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		}
		man-puts <DL><DD>
		foreach more2 [split $more2 \n] {
		    man-puts $more2<BR>
		}
		man-puts </DL></DL><P>
	    } elseif {[match-text .RS .sp @more .sp .RE .fi]} {
		man-puts <P><DL><DD>
		foreach more [split $more \n] {
		    man-puts $more<BR>
		}
		man-puts </DL><P>
	    } else {
		manerror "ignoring $line"
	    }
	}
	.RE - .DE - .CE {
	    manerror "unexpected $code"
	    return







|
|


|

|
|










|






|










|

|










|








|


|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|







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>
	    foreach optionpair [lsort -dictionary -index 0 $optslist] {
		lassign $optionpair option targetPage
		man-puts "<dt><b>[std-option-toc $option $targetPage]</b>"
	    }
	    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>
	}
	.RS {
	    output-RS-list
	    return
	}
	.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>
	    } elseif {[match-text .fi @ul1 @ul2 .nf @stuff .DE]} {
		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>
	    } 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>
		}
	    } elseif {[match-text .RS @more .RE .fi]} {
		man-puts <dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<br>
		}
		man-puts </dl>
	    } elseif {[match-text .RS @more .RS @more2 .RE .RE .fi]} {
		man-puts <dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<br>
		}
		man-puts <dl><dd>
		foreach more2 [split $more2 \n] {
		    man-puts $more2<br>
		}
		man-puts </dl></dl>
	    } elseif {[match-text .RS @more .RS @more2 .RE @more3 .RE .fi]} {
		man-puts <dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<br>
		}
		man-puts <dl><dd>
		foreach more2 [split $more2 \n] {
		    man-puts $more2<br>
		}
		man-puts </dl><dd>
		foreach more3 [split $more3 \n] {
		    man-puts $more3<br>
		}
		man-puts </dl>
	    } elseif {[match-text .sp .RS @more .RS @more2 .sp .RE .RE .fi]} {
		man-puts <p><dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<br>
		}
		man-puts <dl><dd>
		foreach more2 [split $more2 \n] {
		    man-puts $more2<br>
		}
		man-puts </dl></dl><p>
	    } elseif {[match-text .RS .sp @more .sp .RE .fi]} {
		man-puts <p><dl><dd>
		foreach more [split $more \n] {
		    man-puts $more<br>
		}
		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
}

##
## merge copyright listings
##
proc merge-copyrights {l1 l2} {
    set merge {}
    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]} {







|







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 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
## 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

    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]

    # 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>"
    } else {
	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







|
|









>




|

|







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

    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>"
    } else {
	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
	    if {!$verbose} {
		puts stderr ""
	    }
	    manerror "discarding $manual(name)"
	    continue
	}
	set manual(infp) [open $manual(page)]

	set manual(text) {}
	set manual(partial-text) {}
	foreach p {.RS .DS .CS .SO} {
	    set manual($p) 0
	}
	set manual(stack) {}
	set manual(section) {}







>







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
	    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>]
    }
    if {!$verbose} {
	puts stderr ""
    }

    if {![llength $manual(wing-toc)]} {
	fatal "not table of contents."







|







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>]
    }
    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
    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)
	    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>"
	} else {
	    append rows([expr {$n%$nrows}]) \
		"<td> <a href=\"$tail.htm\">$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>"
    close $manual(wing-toc-fp)
    set manual(merge-copyrights) \
	[merge-copyrights $manual(merge-copyrights) $manual(wing-copyrights)]
}

proc makedirhier {dir} {
    try {







|
|



|


|













|







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.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.html\" title=\"[subst $tooltip]\">$name</a> </td>"
	} else {
	    append rows([expr {$n%$nrows}]) \
		"<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>"
    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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env tclsh

if {[catch {package require Tcl 8.6-} msg]} {
    puts stderr "ERROR: $msg"
    puts stderr "If running this script from 'make html', set the\
	NATIVE_TCLSH environment\nvariable to point to an installed\
	tclsh9.0 (or the equivalent tclsh90.exe\non Windows)."
    exit 1
}

# Convert Ousterhout format man pages into highly crosslinked hypertext.
#
# Along the way detect many unmatched font changes and other odd things.
#
# 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

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]

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+\"([^.])+\.([^.\"]+)}] \
	    $data -> major minor]} {
		return [list $major $minor]
	}
    }
}
proc findversion {top name useversion} {
    # Default search version is a glob pattern, switch it for string match:






|














|
|








|













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env tclsh

if {[catch {package require Tcl 8.6-} msg]} {
    puts stderr "ERROR: $msg"
    puts stderr "If running this script from 'make html', set the\
	NATIVE_TCLSH environment\nvariable to point to an installed\
	tclsh8.6 (or the equivalent tclsh86.exe\non Windows)."
    exit 1
}

# Convert Ousterhout format man pages into highly crosslinked hypertext.
#
# Along the way detect many unmatched font changes and other odd things.
#
# 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 © 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 -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] \
		{^#\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
	    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]} {
		    set top [file dirname [file dirname $tclh]]
		    set prefix [file dirname $top]
		    return [list $prefix [file tail $top] $major $minor]
		}
	    }
	}
    }







|







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]} {
		    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
    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 {}} {
	    # 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} {
	    puts stderr "tcltk-man-html: couldn't find Tcl below $tcltkdir"
	    exit 1
	}
	puts "using Tcl source directory $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 {$major eq ""} {
		# obtain version from generic header if we can:
		lassign [getversion [file join $tcltkdir $tcldir generic tk.h]] major minor
	    }
	} else {
	    lassign [findversion $tcltkdir tk $useversion] tcltkdir tkdir major minor
	}
	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 "verbose messages are [expr {$verbose ? {on} : {off}}]"

    # the title for the man pages overall
    global overall_title
    set overall_title ""







|





|



|







|


|




|



|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
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 ""} {
	    # 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} {
	    puts stderr "tcltk-man-html: couldn't find Tcl below $tcltkdir"
	    exit 1
	}
	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 {$major eq ""} {
		# obtain version from generic header if we can:
		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} {
	    puts stderr "tcltk-man-html: couldn't find Tk below $tcltkdir"
	    exit 1
	}
	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
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"

    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;
	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;
	border-bottom:     $hBd;
	margin-top:        0px;
    }
    css-style h2 {
	font-size:         14px;
	color:             #11577b;
	background-color:  #c5dce8;
	padding-left:      1em;
	border:            1px solid #6A6A6A;
    }
    css-style h3 h4 {
	color:             #1674A4;
	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;
	float: left;
	padding: 2px;
	border-top: 1px solid #999;
    }
    css-style ".keylist dt" { font-weight: bold; }
    css-style ".keylist dd" ".arguments dd" {
	margin-left: 20em;
	padding: 2px;
	border-top: 1px solid #999;
    }
    css-style .copy {
	background-color:  #f6fcfc;
	white-space:       pre;
	font-size:         80%;
	border-top:        1px solid #6A6A6A;
	margin-top:        2em;
    }
    css-style .tablecell {
	font-size:	   12px;







|








|



















|





|
|





|










|


|



|

|


|







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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"

    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;
	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;
	border-bottom:     $hBd;
	margin-top:        0px;
    }
    css-style h2 {
	font-size:         14px;
	color:             #11577B;
	background-color:  #C5DCE8;
	padding-left:      1em;
	border:            1px solid #6A6A6A;
    }
    css-style h3 h4 {
	color:             #1674A4;
	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: 25em;
	float: left;
	padding: 2px;
	border-top: 1px solid #999999;
    }
    css-style ".keylist dt" { font-weight: bold; }
    css-style ".keylist dd" ".arguments dd" {
	margin-left: 25em;
	padding: 2px;
	border-top: 1px solid #999999;
    }
    css-style .copy {
	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
##
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]

    puts $cssfd [css-stylesheet]
    close $cssfd
    set manual(short-toc-n) 1
    set manual(short-toc-fp) [open $html/[indexfile] w]

    puts $manual(short-toc-fp) [htmlhead $overall_title $overall_title]
    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
	}







>




>

|







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\">"
    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
    ##
    if {!$verbose} {
	puts stderr "Assembling index"
    }
    file delete -force -- $html/Keywords
    makedirhier $html/Keywords
    set keyfp [open $html/Keywords/[indexfile] w]

    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>"
	} else {
	    # No keywords for this letter
	    lappend keyheader $a
	}
    }
    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]

	puts $afp [htmlhead "$tcltkdesc Keywords - $a" \
		       "$tcltkdesc Keywords - $a" \
		       $overall_title "../[indexfile]"]
	puts $afp $keyheader
	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>"
	    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>"
		} else {
		    lappend refs "<A HREF=\"../$file\">$name</A>"
		}
	    }
	    puts $afp "[join $refs {, }]</DD>"
	}
	puts $afp "</DL>"
	# insert merged copyrights
	puts $afp [copyout $manual(merge-copyrights)]
	puts $afp "</BODY></HTML>"
	close $afp
    }
    # insert merged copyrights
    puts $keyfp [copyout $manual(merge-copyrights)]
    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>"
    # insert merged copyrights
    puts $manual(short-toc-fp) [copyout $manual(merge-copyrights)]
    puts $manual(short-toc-fp) "</BODY></HTML>"
    close $manual(short-toc-fp)

    ##
    ## output man pages
    ##
    unset manual(section)
    if {!$verbose} {







>








|





|







|
>




|


|
|









|

|


|

|


|




|





|
|


|







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.html\">$a</a>"
	} else {
	    # No keywords for this letter
	    lappend keyheader $a
	}
    }
    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.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\">"
	foreach k [lsort -dictionary $keys] {
	    set k [string range $k 8 end]
	    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>"
		} else {
		    lappend refs "<a href=\"../$file\">$name</a>"
		}
	    }
	    puts $afp "[join $refs {, }]</dd>"
	}
	puts $afp "</dl>"
	# insert merged copyrights
	puts $afp [copyout $manual(merge-copyrights)]
	puts $afp "</body></html>"
	close $afp
    }
    # insert merged copyrights
    puts $keyfp [copyout $manual(merge-copyrights)]
    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>"
    # insert merged copyrights
    puts $manual(short-toc-fp) [copyout $manual(merge-copyrights)]
    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
		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]

	    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>"
	} on error msg {
	    if {$verbose} {
		puts stderr $msg
	    } else {
		puts stderr "\nError when processing $manual(name): $msg"
	    }
	} finally {







|
>

















|







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).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>"
	} 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

##
## 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]

	    set d [read $f]
	    close $f
	    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]
    }
}







|
|
>


|







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.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]} {
	       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
    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 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







|







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 {}
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
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
    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_widget.n	{image text variable}
    TclZlib.3		{binary flush filename text}
}
array set exclude_when_followed_by_map {
    canvas.n {
	bind widget
	focus widget







|







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 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
	    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 {



		set f [open [file join $pkgsDir $dir configure.ac]]


		foreach line [split [read $f] \n] {
		    if {2 == [scan $line \
			    { AC_INIT ( [%[^]]] , [%[^]]] ) } n v]} {
			set description [list $n $v]
			break
		    }
		}







>
>
>
|
>
>







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]]
		}
		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

    # 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]

	    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
		}







>







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
    #
    # 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."] \
	[plus-base $build_tk $tkdir doc/*.n {Tk Commands} TkCmd \
	     "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} {







|

|







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."] \
	[plus-base $build_tk $tkdir doc/*.n {Tk Commands} TkCmd \
	     "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
#include <tcl.h>

extern DLLEXPORT Tcl_PackageInitProc 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) {
    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) {
    TsdPerf *perf = Tcl_GetThreadData(&key, sizeof(TsdPerf));


    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(perf->value));

    return TCL_OK;
}


|









|


















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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_LibraryInitProc Tsdperf_Init;

static Tcl_ThreadDataKey key;

typedef struct {
    Tcl_WideInt value;
} TsdPerf;


static int
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(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;
}

Changes to tools/uniClass.tcl.

59
60
61
62
63
64
65
66
67
68
69




70
71
72
73
74
75
76
    set ranges "    "
    set numranges 0
    set chars "    "
    set numchars 0
    set extchars 0
    set extranges 0

    for {set i 0} {$i <= 0x10FFFF} {incr i} {
	if {$i == 0xD800} {
	    # Skip surrogates
	    set i 0xE000




	}
	if {[string is $type [format %c $i]]} {
	    if {$i == ($last + 1)} {
		set last $i
	    } else {
		if {$first >= 0} {
		    emitRange $first $last







|



>
>
>
>







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 <= 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
    }
    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"
    } 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"
    } else {
	puts "/*\n * no singletons of $type characters.\n */\n"
    }
}

puts "/*
 *	Declarations of Unicode character ranges.  This code







|





|







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 ((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 ((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
# 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.
# 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








|







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 © 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

    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
    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.
 * 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.







|







|







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 -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 © 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














{
   TclCreatesocketAddress/getaddrinfo/calloc
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:calloc
   ...
   fun:getaddrinfo
   fun:TclCreateSocketAddress
}

{
   TclCreatesocketAddress/getaddrinfo/malloc
   Memcheck:Leak










   match-leak-kinds: reachable
   fun:malloc
   ...
   fun:getaddrinfo
   fun:TclCreateSocketAddress
}














{
   TclpDlopen/load
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:calloc
   ...
>
>
>
>
>
>
>
>
>
>
>
>
>
>













>
>
>
>
>
>
>
>
>
>






>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
   fun:malloc
   ...
   fun:_nss_systemd_getgrnam_r
   ...
   fun:TclpGetGrNam
}









































{
   TclpGetPwNam/getpwname_r/__nss_next2/calloc
   Memcheck:Leak
   match-leak-kinds: reachable
   fun:calloc
   ...
   fun:__nss_next2







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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
   fun:malloc
   ...
   fun:_nss_systemd_getpwnam_r
   ...
   fun:TclpGetPwNam
}































































{
	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
}








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















>
>
>
>
>
>
>
>
>
>





177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
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.

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			= $(SHELL) $(UNIX_DIR)/install-sh -c
INSTALL_PROGRAM		= ${INSTALL}
INSTALL_LIBRARY		= ${INSTALL}
INSTALL_DATA		= ${INSTALL} -m 644
INSTALL_DATA_DIR	= ${INSTALL} -d -m 755








|
|







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	= 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
# 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_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







|







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@
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
# 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}

#--------------------------------------------------------------------------
# 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.
#--------------------------------------------------------------------------








|







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	= $(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
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

ZLIB_DIR		= ${COMPAT_DIR}/zlib
ZLIB_INCLUDE		= @ZLIB_INCLUDE@
TOMMATH_DIR		= $(TOP_DIR)/libtommath
TOMMATH_INCLUDE		= @TOMMATH_INCLUDE@

CC			= @CC@







|







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_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
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 \

	--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@

CC_SWITCHES = $(STUB_CC_SWITCHES) ${NO_DEPRECATED_FLAGS} -DMP_FIXED_CUTOFFS -DMP_NO_STDINT

APP_CC_SWITCHES = $(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

XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
	tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.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 \
	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 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 \
	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

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_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_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_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 \


	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 \







>









|
|

|

|









|


|
>


|
|











|














|







|
|
|



|





>
>







264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
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@ \
	${NO_DEPRECATED_FLAGS} -DMP_FIXED_CUTOFFS

CC_SWITCHES = $(STUB_CC_SWITCHES) -DBUILD_tcl

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 tclTestABSList.o

XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \
	tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o \
	tclTestABSList.o

GENERIC_OBJS = regcomp.o regexec.o regfree.o regerror.o tclAlloc.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 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 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

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_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_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_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

GENERIC_SRCS = \
	$(GENERIC_DIR)/regcomp.c \
	$(GENERIC_DIR)/regexec.c \
	$(GENERIC_DIR)/regfree.c \
	$(GENERIC_DIR)/regerror.c \
	$(GENERIC_DIR)/tclAlloc.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)/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 \







>






>







400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421

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 \
457
458
459
460
461
462
463

464
465

466
467
468
469
470
471
472
	$(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)/tclStrToD.c \
	$(GENERIC_DIR)/tclTest.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 \







>


>







463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
	$(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 \
484
485
486
487
488
489
490


491
492
493
494
495
496
497
	$(GENERIC_DIR)/tclOODefineCmds.c \
	$(GENERIC_DIR)/tclOOInfo.c \
	$(GENERIC_DIR)/tclOOMethod.c \
	$(GENERIC_DIR)/tclOOStubInit.c

STUB_SRCS = \
	$(GENERIC_DIR)/tclStubLib.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 \







>
>







492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
	$(GENERIC_DIR)/tclOODefineCmds.c \
	$(GENERIC_DIR)/tclOOInfo.c \
	$(GENERIC_DIR)/tclOOMethod.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
	$(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_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_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_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 \







|






|











<



<







<






<






|
>
>
>







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
	$(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_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_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_mag_u32.c \
	$(TOMMATH_DIR)/bn_mp_get_mag_u64.c \
	$(TOMMATH_DIR)/bn_mp_get_mag_ul.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_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_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_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
	$(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_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 \







|







<



<







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
	$(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_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_u32.c \
	$(TOMMATH_DIR)/bn_mp_set_u64.c \
	$(TOMMATH_DIR)/bn_mp_set_ul.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
	$(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


DL_SRCS = \
	$(UNIX_DIR)/tclLoadAix.c \
	$(UNIX_DIR)/tclLoadDl.c \
	$(UNIX_DIR)/tclLoadDl2.c \
	$(UNIX_DIR)/tclLoadDld.c \
	$(UNIX_DIR)/tclLoadDyld.c \







|
>







674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
	$(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)/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
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@

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@








>







731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
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
	@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
	@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 \

	    cat ${TCL_ZIP_FILE} >> ${LIB_FILE}; \



	    ${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 ); \







|














>

>
>
>







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
	@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}/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
# 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}
	${CC} ${CFLAGS} ${LDFLAGS} ${TCLSH_OBJS} \
		@TCL_BUILD_LIB_SPEC@ ${TCL_STUB_LIB_FILE} ${LIBS} @EXTRA_TCLSH_LIBS@ \
		${CC_SEARCH_FLAGS} -o ${TCL_EXE}










# 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
	(cd dltest ; $(MAKE) distclean)

depend:
	makedepend -- $(DEPEND_SWITCHES) -- $(SRCS)

#--------------------------------------------------------------------------
# The following target outputs the name of the top-level source directory for







|



>
>
>
>
>
>
>
>
>

















|







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
# 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_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 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
# 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}
	$(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}










# 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
	@echo "set env TCL_LIBRARY=${TCL_BUILDTIME_LIBRARY}" >> gdb.run
	@echo "set args $(TOP_DIR)/tests/all.tcl $(TESTFLAGS) -singleproc 1" >> gdb.run
	$(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 \
		$(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...







|






>
>
>
>
>
>
>
>
>















|
<
|
<
<


<
<
|

|







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
# 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} ${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}
	$(SHELL_ENV) $(GDB) --args ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl \

		$(TESTFLAGS) -singleproc 1



lldb-test: ${TCLTEST_EXE}


	$(SHELL_ENV) $(LLDB) -- ./${TCLTEST_EXE} $(TOP_DIR)/tests/all.tcl \
		$(TESTFLAGS) -singleproc 1


# 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
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}




valgrind: ${TCL_EXE} ${TCLTEST_EXE}
	$(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCLTEST_EXE} \
		$(TOP_DIR)/tests/all.tcl -singleproc 1 -constraints valgrind \
		$(TESTFLAGS)






















valgrindshell: ${TCL_EXE}
	$(SHELL_ENV) $(VALGRIND) $(VALGRINDARGS) ./${TCL_EXE} $(SCRIPT)

trace-shell: ${TCL_EXE}
	$(SHELL_ENV) ${TRACE} $(TRACE_OPTS) ./${TCL_EXE} $(SCRIPT)








>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
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 $@)) > [email protected] 2>&1
	@mv [email protected] $@
.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
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-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"; \







|
|







1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
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="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
	    @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 \

	    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
	@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
	@echo "Installing package cookiejar 0.2 files to $(SCRIPT_INSTALL_DIR)/cookiejar0.2/"
	@for i in $(TOP_DIR)/library/cookiejar/*.tcl; do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \
	done
	@for i in $(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"
	@$(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"
	@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"
	@$(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"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/platform-1.0.14.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"; \
	fi

install-tzdata:
	@for i in tzdata; do \
	    if [ ! -d "$(SCRIPT_INSTALL_DIR)/$$i" ] ; then \
		echo "Making directory $(SCRIPT_INSTALL_DIR)/$$i"; \







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







|
|
>












|




|

|
<
<
|
>

|
|

|
|






|

|
|

|









|







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
	    @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: 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 \
	    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;
	@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;
	@echo "Installing package cookiejar 0.2 files to $(SCRIPT_INSTALL_DIR)/cookiejar0.2/"
	@for i in $(TOP_DIR)/library/cookiejar/*.tcl \


	          $(TOP_DIR)/library/cookiejar/*.gz; \
	    do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/cookiejar0.2"; \
	    done
	@echo "Installing package http 2.10b2 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/http/http.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/http-2.10b2.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.8 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/tcltest-2.5.8.tm"
	@echo "Installing package platform 1.0.19 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/platform-1.0.19.tm"
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/platform/shell-1.1.4.tm"
	@echo "Installing encoding files to $(SCRIPT_INSTALL_DIR)/encoding/"
	@for i in $(TOP_DIR)/library/encoding/*.enc; do \
		$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done
	@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 [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"; \
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
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}\""


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




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
	$(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclClock.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
	$(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







>




















>
>
>
















|

>
>
>










|







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
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 $(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 $(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

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
	$(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







|







1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366

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 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
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
		-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







<







1508
1509
1510
1511
1512
1513
1514

1515
1516
1517
1518
1519
1520
1521
		-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)\"" \

		$(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

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




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







>
>
>







1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553

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
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) \
		-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)
	$(CC) -c $(APP_CC_SWITCHES) $(GENERIC_DIR)/tclTest.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








|

<

<



|

>
>
>







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
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) -D_GNU_SOURCE \
		-DCFG_RUNTIME_DLLFILE="\"$(TCL_LIB_FILE)\"" \

		-DCFG_RUNTIME_LIBDIR="\"$(libdir)\"" \

		-I$(ZLIB_DIR) -I$(ZLIB_DIR)/contrib/minizip \
		$(GENERIC_DIR)/tclZipfs.c

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

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_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_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








|
|




|
|







1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679

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_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_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

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_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)







>
>
>
>
>
>







1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749

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

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_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)







>
>
>







1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803

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

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
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclEpollNotfy.c

tclKqueueNotfy.o: $(UNIX_DIR)/tclKqueueNotfy.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclKqueueNotfy.c

tclSelectNotfy.o: $(UNIX_DIR)/tclSelectNotfy.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







|


|


|







1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840

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 $(UNIX_DIR)/tclUnixNotfy.c
	$(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tclEpollNotfy.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 $(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
#--------------------------------------------------------------------------
# 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







<
<
<



<
<
<



<
<
<
<
<
<
<
<
<







1900
1901
1902
1903
1904
1905
1906



1907
1908
1909



1910
1911
1912









1913
1914
1915
1916
1917
1918
1919
#--------------------------------------------------------------------------
# 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.
#--------------------------------------------------------------------------




mkstemp.o: $(COMPAT_DIR)/mkstemp.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/mkstemp.c




strncasecmp.o: $(COMPAT_DIR)/strncasecmp.c
	$(CC) -c $(STUB_CC_SWITCHES) $(COMPAT_DIR)/strncasecmp.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

#--------------------------------------------------------------------------
# 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 $(GENERIC_DIR)/tclStubLib.c

tclTomMathStubLib.o: $(GENERIC_DIR)/tclTomMathStubLib.c
	$(CC) -c $(STUB_CC_SWITCHES) $(GENERIC_DIR)/tclTomMathStubLib.c

tclOOStubLib.o: $(GENERIC_DIR)/tclOOStubLib.c
	$(CC) -c $(STUB_CC_SWITCHES) $(GENERIC_DIR)/tclOOStubLib.c

.c.o:
	$(CC) -c $(CC_SWITCHES) $<

#--------------------------------------------------------------------------
# Minizip implementation
#--------------------------------------------------------------------------







>
>
>
>
>
>
>
>
>
>
|


|


|







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

#--------------------------------------------------------------------------
# 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)/tclStubLibTbl.c

tclTomMathStubLib.o: $(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) @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
# 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


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 $(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 $(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 $(PKG_DIR)/$$pkg/Makefile ] ; then \
		    echo "Installing package '$$pkg'"; \
		    ( cd $(PKG_DIR)/$$pkg; $(MAKE) install \
			  "DESTDIR=$(INSTALL_ROOT)"; ) || exit $$?; \
		fi; \
	    fi; \
	done







>







>
>
>
>
>
>
>
>
















>
>
>
>











>
>
>
>
>







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
# 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
	    fi; \
	done

clean-packages:
	@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; ) \
		fi; \
	    fi; \
	done

distclean-packages:
	@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; ) \
		fi; \
		rm -rf $(PKG_DIR)/$$pkg; \
	    fi; \
	done; \

	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 \







>
>
>










>
>
>
>






>







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
	    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

# 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.



gendate:
	bison --output-file=$(GENERIC_DIR)/tclDate.c \
		--no-lines \
		--name-prefix=TclDate \
		$(GENERIC_DIR)/tclGetDate.y

#	yacc -l $(GENERIC_DIR)/tclGetDate.y







>
>







2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168

# 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
# 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

$(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 $@






$(TOP_DIR)/manifest.uuid:
	printf "git." >$(TOP_DIR)/manifest.uuid
	git rev-parse HEAD >>$(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







|
|
|









>
>
>
>
>

|
|
>
>
>







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
# 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   = $(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
	(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
		$(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 \
		$(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
	$(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)/tests
	$(DIST_INSTALL_DATA) $(TOP_DIR)/license.terms $(DISTDIR)/tests
	$(DIST_INSTALL_DATA) $(TOP_DIR)/tests/*.test $(TOP_DIR)/tests/README \

		$(TOP_DIR)/tests/httpd $(TOP_DIR)/tests/*.tcl \






		$(DISTDIR)/tests

















	$(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
	$(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 \
		$(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 \
		$(TOOL_DIR)/configure $(TOOL_DIR)/configure.ac \
		$(TOOL_DIR)/*.tcl $(TOOL_DIR)/man2tcl.c \
		$(TOOL_DIR)/*.bmp $(TOOL_DIR)/tcl.hpj.in \
		$(DISTDIR)/tools
	chmod 755 $(DISTDIR)/tools/checkLibraryDoc.tcl \
		$(DISTDIR)/tools/configure $(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




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.
#
# 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







|
|
<








|



















>
>
>
>
>



>

>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
>
>
|





<










<
<
<
<








|
<
|
<
|

|



<
<






>
>
>












|







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
		$(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.md $(TOP_DIR)/README.md \
		$(TOP_DIR)/license.terms $(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/*.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/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 $(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.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 \
		$(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.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)/README $(TOOL_DIR)/*.c $(TOOL_DIR)/*.svg \

		$(TOOL_DIR)/*.tcl $(TOOL_DIR)/*.bmp $(TOOL_DIR)/valgrind_suppress \

		$(TOOL_DIR)/valgrind_check_success $(DISTDIR)/tools
	chmod 755 $(DISTDIR)/tools/checkLibraryDoc.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)/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
	$(DIST_INSTALL_DATA) $(TOP_DIR)/.travis.yml $(DISTDIR)
	$(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.* &
# 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

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)" \

		--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

#--------------------------------------------------------------------------
# DO NOT DELETE THIS LINE -- make depend depends on it.







|
>

















|



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

html-tk: ${NATIVE_TCLSH}
	$(BUILD_HTML) --tk
	@EXTRA_BUILD_HTML@

BUILD_HTML = \
	@${NATIVE_TCLSH} $(TOOL_DIR)/tcltk-man2html.tcl \
		--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: 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
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

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

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










|



|







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:
	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:
	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
				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
	--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.







|







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 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
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for tcl 9.0.
#
#
# 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
test \$(( 1 + 1 )) = 2 || 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 [email protected] 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


|


|
>










|
>






|
|




>




>
>
>
>
>
>
>
>



<
<
<
<
<
<
<
<
|
|
<
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
>
>
|
<
<
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>


|








<
<
<
<
<
<
<








>
|
>
>
>
|





|





|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















|
|
|




|
>






|
|




>














|
>

|
|
>


>
>






|
>

|
|
>

|
>

|
|




>
|
>
>
>





|

|
>

|
>







>
>
>
>
>
|
|
>

>
>
|
<


|
>
















|
|



|
>
|
|
|
|
|

|





|
>



















>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47








48
49

50
51






52







53
54
55
56


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113




















114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
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.72 for tcl 9.0.
#
#
# 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 ${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 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








IFS=" ""	$as_nl"


PS1='$ '
PS2='> '






PS4='+ '








# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL


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 ${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









# 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 #(((
    '') 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'
# 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
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi






















# 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'.
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 \${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 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 :

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 :
  as_have_required=yes
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 :

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 #(((
    '') 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
	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
		    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_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 #(
  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



      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'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi

    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
    printf "%s\n" "$0: Please tell [email protected] 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 ;;
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
  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







|








|







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=`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 ||
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
} # 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







|
>




|
|


|
>







|
>




|
|


|
>













|

|







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 :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
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 :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
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
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  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
  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







|







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 ||
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
  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







>
>











|













>
>
>
>












>
>
>
>
>
>












|
|
|







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" ||
    { 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'.
    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
  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,







|
>


|
>







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_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_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
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>
#endif
#ifdef HAVE_SYS_STAT_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_UNISTD_H
# include <unistd.h>
#endif"


ac_subst_vars='DLTEST_SUFFIX
DLTEST_LD
EXTRA_TCLSH_LIBS
EXTRA_BUILD_HTML
EXTRA_INSTALL_BINARIES
EXTRA_INSTALL
EXTRA_APP_CC_SWITCHES







|
|
|

|
<
<
<

<
<
<
<
<


<
<
<


<
<
<






>
>
>
>
>
>
>
>
>




>







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 <stddef.h>
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H



# include <stdlib.h>





#endif
#ifdef HAVE_STRING_H



# include <string.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
TCL_LIB_FILE
PKG_CFG_ARGS
TCL_YEAR
TCL_PATCH_LEVEL
TCL_MINOR_VERSION
TCL_MAJOR_VERSION
TCL_VERSION

INSTALL_MSGS
INSTALL_LIBRARIES
TCL_ZIP_FILE
ZIPFS_BUILD
ZIP_INSTALL_OBJS
ZIP_PROG_VFSSEARCH
ZIP_PROG_OPTIONS
ZIP_PROG

EXEEXT_FOR_BUILD
CC_FOR_BUILD
DTRACE
LDFLAGS_DEFAULT
CFLAGS_DEFAULT
INSTALL_STUB_LIB
DLL_INSTALL_DIR







>








>







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
TCL_SHLIB_LD_EXTRAS
SHLIB_LD
STLIB_LD
LD_SEARCH_FLAGS
CC_SEARCH_FLAGS
LDFLAGS_OPTIMIZE
LDFLAGS_DEBUG

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


ZLIB_INCLUDE
ZLIB_SRCS
ZLIB_OBJS
TCLSH_PROG
SHARED_BUILD
EGREP
GREP
CPP
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS







>















>
>





<
<







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


CPP
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
739
740
741
742
743
744
745

746
747
748
749
750
751
752
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir

localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir







>







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
enable_corefoundation
enable_load
enable_symbols
enable_langinfo
enable_dll_unloading
with_tzdata
enable_dtrace
enable_zipfs
enable_framework
'
      ac_precious_vars='build_alias
host_alias
target_alias
CC
CFLAGS
LDFLAGS







|
|







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_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
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_TARNAME}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'







>







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

  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=*)







<
<







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



  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
  | --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







|

|







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'"
    ac_useropt_orig=$ac_useropt
    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
  -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







|

|







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'"
    ac_useropt_orig=$ac_useropt
    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
    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 ;;








>
>
>
>
>
>
>
>
>







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
  -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







|

|













|

|







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'"
    ac_useropt_orig=$ac_useropt
    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'"
    ac_useropt_orig=$ac_useropt
    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
  -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.







|
|







|






|

|















|







|
















|







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"
    ;;

  *=*)
    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.
    printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
      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" ;;
    *)     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 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'
# 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
  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







|







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 ||
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
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







|







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_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
#
# 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.

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]







|













|

|

|







|
|
|
|










>







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.

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]
  --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
  --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)


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:
                          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
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|^\.[\\/]||'`
  # 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







<


>




|
<















|


















|

|







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-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: 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
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=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  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
    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
tcl configure 9.0
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. ##
## ------------------------ ##

# 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
  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
  (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
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest.$ac_objext; then :

  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1

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 ()
{
  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack







  rm -f conftest.$ac_objext 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>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; } && {
	 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
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

# 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
  (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
  test $ac_status = 0; } > conftest.i && {
	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
	 test ! -s conftest.err

       }; then :
  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

    ac_retval=1

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
# 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
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

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_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
/* 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.
    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
    <limits.h> exists even on freestanding compilers.  */

#ifdef __STDC__
# 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 ();
/* 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 ()
{
return $2 ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  eval "$3=yes"
else
  eval "$3=no"

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext 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_func

# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
# ---------------------------------------------
# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
# accordingly.
ac_fn_c_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



  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$4
int
main ()
{
#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 :

  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_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"
  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
  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













































# 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
/* end confdefs.h.  */
$5
int
main ()
{
static $2 ac_aggr;
if (ac_aggr.$3)
return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  eval "$4=yes"
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$5
int
main ()
{
static $2 ac_aggr;
if (sizeof ac_aggr.$3)
return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  eval "$4=yes"
else
  eval "$4=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
eval ac_res=\$$4
	       { $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_member




















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

  $ $0 $@

_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##







|
>







|









|

|
















|






|







|



|
>

|
|


|
>






|
|
|
>
|


>
>
>
>
>
>
>
|
>
>
>
|
>
>
|
<
|

<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
|

<
<
<
<
<
>
>
>

<

|













|







|



>
|

|
|


|
>






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
<
|


>






|
|

>
>
>
>
>
|
|
|
<
<
|
<
|
|
|
<
>
|

|
<
|


|
>

>
>
>
>




|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







|
|
>
|
|
|
|






|
<
<

<
|
<
<
<
<








|








|






|
>

|
|
>

|
|
>


|
|




|
|

|
|



<
|
|
>
|
|
|
>
>
>




|













|
>

|
|
>

|
>
>
>


|
|


|








|
|
>
|
|
|
|




|







|
>




|







|
>

|
|
>

|

|
>


|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|
|
>
|
|
|
|



|








|
>

|
|



|








|
>

|
|
>

|
>

|
>


|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|

|







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 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
      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.72

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 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\""
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
  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 :
  ac_retval=0
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	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_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\""
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
  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 :
  ac_retval=0
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

    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_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.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\""
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
  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 :
  ac_retval=0
else case e in #(

  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	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
































# 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
  { 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 (void); below.  */




#include <limits.h>




#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 (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 (void)
{
return $2 ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$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_exeext 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_func

# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR
# ------------------------------------------------------------------
# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
# 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/ *(.*//'`

  { 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 (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 :
  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
  eval $6=\$ac_save_FLAGS
 ;;
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_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
  { 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_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
  { 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 (void)
{
static $2 ac_aggr;
if (ac_aggr.$3)
return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  eval "$4=yes"
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
$5
int
main (void)
{
static $2 ac_aggr;
if (sizeof ac_aggr.$3)
return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  eval "$4=yes"
else case e in #(
  e) eval "$4=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
eval ac_res=\$$4
	       { 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.72.  Invocation command line was

  $ $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

_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








>
|
>
>
>
|







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 #(((
    '') 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
  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.







|







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=`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

# 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







>
>




|










|
|







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

    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_*) { 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
      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






TCL_VERSION=9.0
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=0
TCL_PATCH_LEVEL="a2"
VERSION=${TCL_VERSION}

EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}

#------------------------------------------------------------------------
# Setup configure arguments for bundled packages







|







|

|




|







|

|





|







|
|













|



<
|
<

<
|
<

<
|
<

<
|
<

<
|
<

<
|
<




<
<

<
|
<
<
<
<

|
<

|
<

>
|

|
>
>
>
>
>
|
|
|


|
|

|







|
|






|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|
|


|
|








|
|


|
|


|
|
|
|





|









|
|
|
|
>
|



















|







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

    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=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
      esac
      printf "%s\n" "$ac_var='\''$ac_val'\''"
    done | sort
    echo

    if test -n "$ac_subst_files"; then
      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=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
	esac
	printf "%s\n" "$ac_var='\''$ac_val'\''"
      done | sort
      echo
    fi

    if test -s confdefs.h; then
      printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
      echo
      cat confdefs.h
      echo
    fi
    test "$ac_signal" != 0 &&
      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

printf "%s\n" "/* confdefs.h */" > confdefs.h

# Predefined preprocessor variables.


printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h



# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.


if test -n "$CONFIG_SITE"; then

  ac_site_files="$CONFIG_SITE"




elif test "x$prefix" != xNONE; then
  ac_site_files="$prefix/share/config.site $prefix/etc/config.site"

else
  ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"

fi

for ac_site_file in $ac_site_files
do
  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" \
      || { { 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; }
  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
    { 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
  { 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,)
      { 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)
      { 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
	  { 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
	  { 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
	{ 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=`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
  { 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="b2"
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
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; }
    # Check whether --enable-man-symlinks was given.
if test "${enable_man_symlinks+set}" = set; then :

  enableval=$enable_man_symlinks; test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"
else
  enableval="no"

fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
$as_echo "$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; }
    # Check whether --enable-man-compression was given.
if test "${enable_man_compression+set}" = set; 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"

fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
$as_echo "$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; }
	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; }
    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; }
    # Check whether --enable-man-suffix was given.
if test "${enable_man_suffix+set}" = set; 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"

fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
$as_echo "$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
  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

  test -z "$as_dir" && as_dir=.



    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}gcc"
    $as_echo "$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
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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="gcc"
    $as_echo "$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
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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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;}
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
  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

  test -z "$as_dir" && as_dir=.



    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}cc"
    $as_echo "$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
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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
       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
    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+' '}$@"
  fi
fi
fi

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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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$ac_prog"
    $as_echo "$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
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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="$ac_prog"
    $as_echo "$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
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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi










































































































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;}
as_fn_error $? "no acceptable C compiler found in \$PATH
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
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion; 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
  (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
  test $ac_status = 0; }
done

cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  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[^ ]*//'`

# 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
  (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'
# 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;
	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'
	# 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=''

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
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;}
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; }

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; }
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; }
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; }; 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;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }

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; }

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 ()
{
FILE *f = fopen ("conftest.out", "w");


 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; }
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
  (eval "$ac_link") 2>&5
  ac_status=$?
  $as_echo "$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
  (eval "$ac_try") 2>&5
  ac_status=$?
  $as_echo "$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; }
    fi
  fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
$as_echo "$cross_compiling" >&6; }

rm -f conftest.$ac_ext conftest$ac_cv_exeext 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
/* end confdefs.h.  */

int
main ()
{

  ;
  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
  (eval "$ac_compile") 2>&5
  ac_status=$?
  $as_echo "$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
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;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }

fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
$as_echo "$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
/* end confdefs.h.  */

int
main ()
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  ac_compiler_gnu=yes
else
  ac_compiler_gnu=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
$as_echo "$ac_cv_c_compiler_gnu" >&6; }


if test $ac_compiler_gnu = yes; then
  GCC=yes
else
  GCC=
fi
ac_test_CFLAGS=${CFLAGS+set}
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
   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 ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  ac_cv_prog_cc_g=yes
else
  CFLAGS=""
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :


else
  ac_c_werror_flag=$ac_save_c_werror_flag
	 CFLAGS="-g"
	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  return 0;
}
_ACEOF
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

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag

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
  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



{ $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
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;
}

/* 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 \
	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"; then :

  ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
  test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC

fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c89" in
  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; } ;;
  *)

    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; } ;;

esac

if test "x$ac_cv_prog_cc_c89" != xno; then :



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
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; }
#endif

_ACEOF
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
  test "$ac_cv_c_inline" != no && break
done


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
$as_echo "$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;;







|
|

|
>

|
|
>


|
|

|
|

|
>





|
|
>


|
|

|
|





|
|


|
|

|
>





|
|
>


|
|













>
>
>
>
>
>
>
>
>









|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|








|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|







|
|












|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|








|
|
|
>
|
|
|







>
|
>
>
>

|
|




|















|


|
>



|
|

|
|










|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|












|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|











|
|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
|

|


|


|






|









|







|











|
|
|




















|


|
|
>
|
|














|




|










|
|
>

|
>
|
|
|


|
|

|
|
|
|
>

|
|
|
|




|
|






|


|
|
>
|
|
|
|









|
|
|

|
>


|
|








|


>
>









|
|







|


|







|


|






|
|
|
|
|



|
|

|
>

|
|
|
>
|
|
|



|













|


|
|
>








|
|


|
|

|
>

|
>

|
|


|
|
|
>
|
|
|



|









|
>

|
|
>

|

|
>

|
|
>
>





|

|
|
|
>
|
|
|







|






|
>

|
|




|






|
>

|
|





|






|
>


|
>

|
>

|
|
>

|
|
|














>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
<


|
>


|



|
|

|
|
<
<
<
|
|
|
<
>
|
>
>
>
>
|
|
>

>
|
|
>
>









|
|
|
>
|
|
|





|
|



|
>


|


|
>

|
|







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?
#------------------------------------------------------------------------


    { 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+y}
then :
  enableval=$enable_man_symlinks; test "$enableval" != "no" && MAN_FLAGS="$MAN_FLAGS --symlinks"
else case e in #(
  e) enableval="no" ;;
esac
fi

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
printf "%s\n" "$enableval" >&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+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 case e in #(
  e) enableval="no" ;;
esac
fi

    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5
printf "%s\n" "$enableval" >&6; }
    if test "$enableval" != "no"; then
	{ 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"
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $Z" >&5
printf "%s\n" "$Z" >&6; }
    fi

    { 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+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 case e in #(
  e) enableval="no" ;;
esac
fi

    { 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
{ 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}gcc"
    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 "gcc", so it can be a program name with args.
set dummy gcc; 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="gcc"
    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

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
{ 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}cc"
    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
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
{ 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 #(((
    '') 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
       ac_prog_rejected=yes
       continue
     fi
    ac_cv_prog_CC="cc"
    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+' '}$@"
  fi
fi
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 "$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
{ 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$ac_prog"
    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


    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
{ 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="$ac_prog"
    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


  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:)
{ 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" && { { 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; }

# Provide some information about the compiler.
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 -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\""
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
  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 (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.
{ 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\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link_default") 2>&5
  ac_status=$?
  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+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'
	# 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 case e in #(
  e) ac_file='' ;;
esac
fi
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

{ { 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 case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; } ;;
esac
fi
{ 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
{ 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\""
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; }
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 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; } ;;
esac
fi
rm -f conftest conftest$ac_cv_exeext
{ 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 (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.
{ 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\""
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; }
  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\""
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
    cross_compiling=no
  else
    if test "$cross_compiling" = maybe; then
	cross_compiling=yes
    else
	{ { 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
{ 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.o conftest.obj conftest.out
ac_clean_files=$ac_clean_files_save
{ 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 (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\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>&5
  ac_status=$?
  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 case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&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 $? "cannot compute suffix of object files: cannot compile
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext ;;
esac
fi
{ 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
{ 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 (void)
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_compiler_gnu=yes
else case e in #(
  e) ac_compiler_gnu=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
 ;;
esac
fi
{ 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+y}
ac_save_CFLAGS=$CFLAGS
{ 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
else case e in #(
  e) CFLAGS=""
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
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
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag ;;
esac
fi
{ 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 :
  { 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.  */





















$ac_c_conftest_c89_program



























_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"

do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c89=$ac_arg
fi
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 ;;
esac
fi

if test "x$ac_cv_prog_cc_c89" = 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_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
  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


{ 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 (void) {return 0; }
$ac_kw foo_t foo (void) {return 0; }
#endif

_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_c_inline=$ac_kw
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
  test "$ac_cv_c_inline" != no && break
done
 ;;
esac
fi
{ 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
#	- 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_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

# 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 :
  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
  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
fi


    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*

    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 :

else
  tcl_ok=0
fi
rm -f 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 :

else
  tcl_ok=0

fi
rm -f conftest*


    # 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


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 :


else

$as_echo "#define NO_DLFCN_H 1" >>confdefs.h


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 :
  cat >>confdefs.h <<_ACEOF
#define HAVE_SYS_PARAM_H 1
_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

	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_cc_pipe=yes
else
  tcl_cv_cc_pipe=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
	CFLAGS=$hold_cflags

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5
$as_echo "$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 :

  withval=$with_encoding; with_tcencoding=${withval}
fi


    if test x"${with_tcencoding}" != x ; then

cat >>confdefs.h <<_ACEOF
#define TCL_CFGVAL_ENCODING "${with_tcencoding}"
_ACEOF

    else

$as_echo "#define TCL_CFGVAL_ENCODING \"utf-8\"" >>confdefs.h

    fi


#--------------------------------------------------------------------
# Look for libraries that we will need when compiling the Tcl shell
#--------------------------------------------------------------------





















































































    #--------------------------------------------------------------------
    # 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 :

  MATH_LIBS=""
else
  MATH_LIBS="-lm"

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
LIBS="-linet  $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */


int
main ()
{
return main ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_inet_main=yes
else
  ac_cv_lib_inet_main=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  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 :



$as_echo "#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:







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
|





|
>
|
|
|
|






<
<




<
|
<
<
<


|
>

|
|
|
>









|
>


|
|

|
>




|

|
>





|
>





|
|





<
<




<
|
<
<
<


|
>

|
|
|
>









|
>


|
|

|
>




|

|
>

|
|
|

|
>









|
|
|
>
|
|
|
|





>
|
>
>
>
|
>

|
|
|
|
|

|
>


|





|
|


|

|
|







|




|
<
>


|


<
<
<
|
|
<
<
<
<
<
<
<
|
|
|
|





>
|
>
>
>
|
>

|
|
|
|
|

|
>


|





|
|


|

|
|







|




|



|

|
>
|
>

|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
|
|
<
<
<
<
<
|
>
>
|
>
|

<

<
<
|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<

|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







|
|
<
<
<
<

<
<
<
<
<
<
<
<
|
|
>

|







|



|
|
>

|
|
|
|
>


<
|
|
>

|
|
|
|
>



<

<
<
|
|
|
|
<



<
<














|
|
|
>
|
|
|





|






|
>

|
|
>

|
|
>

|
|












|
>






<
|
<



|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







|
>

|
|
>








|
|
|
>
|
|
|






|






|
>

|
|
>

|

|
>

|
|
|
>



|
|
>


|


<







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
#	- 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
{ 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

















    ac_fn_c_check_header_compile "$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 case e in #(
  e) tcl_ok=0 ;;
esac
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_TRADITIONAL "strstr" >/dev/null 2>&1






























































then :




















































else case e in #(


















  e) tcl_ok=0 ;;

esac











fi
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_TRADITIONAL "strerror" >/dev/null 2>&1
then :













else case e in #(
  e) tcl_ok=0 ;;
esac
fi
rm -rf conftest*


    # See also memmove check below for a place where NO_STRING_H can be
    # set and why.

    if test $tcl_ok = 0; then

printf "%s\n" "#define NO_STRING_H 1" >>confdefs.h

    fi

    ac_fn_c_check_header_compile "$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 case e in #(
  e)
printf "%s\n" "#define NO_SYS_WAIT_H 1" >>confdefs.h
 ;;
esac
fi


    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 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).


    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
then :
  printf "%s\n" "#define HAVE_SYS_PARAM_H 1" >>confdefs.h


fi





#--------------------------------------------------------------------
# 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
    { 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_cc_pipe=yes
else case e in #(
  e) tcl_cv_cc_pipe=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_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+y}
then :
  withval=$with_encoding; with_tcencoding=${withval}
fi


    if test x"${with_tcencoding}" != x ; then


printf "%s\n" "#define TCL_CFGVAL_ENCODING \"${with_tcencoding}\"" >>confdefs.h


    else

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 :
  MATH_LIBS=""
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.
    #--------------------------------------------------------------------

    { 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 (void)
{
return main ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_inet_main=yes
else case e in #(
  e) ac_cv_lib_inet_main=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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_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 :


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
    #	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 :

  tcl_checkSocket=0
else
  tcl_checkSocket=1

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 :


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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char setsockopt ();
int
main ()
{
return setsockopt ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_socket_setsockopt=yes
else
  ac_cv_lib_socket_setsockopt=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  LIBS="$LIBS -lsocket"
else
  tcl_checkBoth=1

fi


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 :

  tcl_checkNsl=0
else
  LIBS=$tk_oldLibs

fi

    fi
    ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char gethostbyname ();
int
main ()
{
return gethostbyname ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_nsl_gethostbyname=yes
else
  ac_cv_lib_nsl_gethostbyname=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  LIBS="$LIBS -lnsl"
fi


fi



$as_echo "#define _REENTRANT 1" >>confdefs.h


$as_echo "#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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_init ();
int
main ()
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
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

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  tcl_ok=yes
else
  tcl_ok=no

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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char __pthread_mutex_init ();
int
main ()
{
return __pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
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

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  tcl_ok=yes
else
  tcl_ok=no

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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_init ();
int
main ()
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
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

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  _ok=yes
else
  tcl_ok=no

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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_init ();
int
main ()
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
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

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  tcl_ok=yes
else
  tcl_ok=no

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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char pthread_mutex_init ();
int
main ()
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
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

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  tcl_ok=yes
else
  tcl_ok=no

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;}
		fi
	    fi
	fi
    fi

    # Does the pthread-implementation provide
    # 'pthread_attr_setstacksize' ?

    ac_saved_libs=$LIBS
    LIBS="$LIBS $THREADS_LIBS"

    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
#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_have_decl=1
else
  ac_have_decl=0

fi

cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_PTHREAD_MUTEX_RECURSIVE $ac_have_decl
_ACEOF
if test $ac_have_decl = 1; then :

  tcl_ok=yes
else
  tcl_ok=no

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; }
    # Check whether --enable-shared was given.
if test "${enable_shared+set}" = set; then :

  enableval=$enable_shared; tcl_ok=$enableval
else
  tcl_ok=yes
fi


    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5
$as_echo "shared" >&6; }
	SHARED_BUILD=1
    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5
$as_echo "static" >&6; }
	SHARED_BUILD=0

$as_echo "#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

	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


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; }
    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; }
    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_type "$LINENO" "gz_header" "ac_cv_type_gz_header" "#include <zlib.h>
"
if test "x$ac_cv_type_gz_header" = xyes; then :


else
  zlib_ok=no

fi

else

  zlib_ok=no

fi


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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char deflateSetHeader ();
int
main ()
{
return deflateSetHeader ();
  ;
  return 0;
}
_ACEOF
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 :

  ac_cv_search_deflateSetHeader=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext
  if ${ac_cv_search_deflateSetHeader+:} false; then :

  break
fi
done
if ${ac_cv_search_deflateSetHeader+:} false; then :


else
  ac_cv_search_deflateSetHeader=no

fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_deflateSetHeader" >&5
$as_echo "$ac_cv_search_deflateSetHeader" >&6; }
ac_res=$ac_cv_search_deflateSetHeader
if test "$ac_res" != no; then :

  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"

else

    zlib_ok=no


fi

fi
if test $zlib_ok = no; then :


  ZLIB_OBJS=\${ZLIB_OBJS}

  ZLIB_SRCS=\${ZLIB_SRCS}

  ZLIB_INCLUDE=-I\${ZLIB_DIR}


fi

$as_echo "#define HAVE_ZLIB 1" >>confdefs.h


#------------------------------------------------------------------------
#	Add stuff for libtommath

libtommath_ok=yes

# Check whether --with-system-libtommath was given.
if test "${with_system_libtommath+set}" = set; 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_type "$LINENO" "mp_int" "ac_cv_type_mp_int" "#include <tommath.h>
"
if test "x$ac_cv_type_mp_int" = xyes; then :


else
  libtommath_ok=no

fi

else

	libtommath_ok=no

fi


    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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char mp_log_u32 ();
int
main ()
{
return mp_log_u32 ();
  ;
  return 0;
}
_ACEOF
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

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  MATH_LIBS="$MATH_LIBS -ltommath"
else

    libtommath_ok=no

fi

fi
fi
if test $libtommath_ok = yes; then :




$as_echo "#define TCL_WITH_EXTERNAL_TOMMATH 1" >>confdefs.h



else



  TOMMATH_OBJS=\${TOMMATH_OBJS}

  TOMMATH_SRCS=\${TOMMATH_SRCS}

  TOMMATH_INCLUDE=-I\${TOMMATH_DIR}



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
  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

  test -z "$as_dir" && as_dir=.



    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_RANLIB="${ac_tool_prefix}ranlib"
    $as_echo "$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
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
$as_echo "$RANLIB" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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_RANLIB="ranlib"
    $as_echo "$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
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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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;}
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; }
    # Check whether --enable-64bit was given.
if test "${enable_64bit+set}" = set; then :

  enableval=$enable_64bit; do64bit=$enableval
else
  do64bit=no

fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5
$as_echo "$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; }
    # Check whether --enable-64bit-vis was given.
if test "${enable_64bit_vis+set}" = set; then :

  enableval=$enable_64bit_vis; do64bitVIS=$enableval
else
  do64bitVIS=no

fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5
$as_echo "$do64bitVIS" >&6; }
    # Force 64bit on with VIS
    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

	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 ()
{
f();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_cc_visibility_hidden=yes
else
  tcl_cv_cc_visibility_hidden=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
	CFLAGS=$hold_cflags

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 :



$as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h


$as_echo "#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; }
    # Check whether --enable-rpath was given.
if test "${enable_rpath+set}" = set; then :

  enableval=$enable_rpath; doRpath=$enableval
else
  doRpath=yes

fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5
$as_echo "$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

	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;}
		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


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5
$as_echo "$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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char dlopen ();
int
main ()
{
return dlopen ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_dl_dlopen=yes
else
  ac_cv_lib_dl_dlopen=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  have_dl=yes
else
  have_dl=no

fi


    # Require ranlib early so we can override it in special cases below.










|
>

|
|
>




|
>

|
|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>

|
>







|
>

|
|
>




|
>

|
|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>


|
>




|


|

|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>








|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>








|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>






|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>



|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>






|
|










>
|
|
>
|
>
|
>
|
|
<
<


<




|
|
|
>

|
|
>

<
<
|
<
|
>

|
|
>








|
|

|
>

|
|
<
|
<
<
<
<
<
<
|


|
|


|
|


|












|
|
|
>
|
|
|












|
>





|
|



|
|












|
|
>



|
>

|
|
>


|
|
|
>


<
|
>

|
|
|
>
|
|
|





|
>
>
>



|

|






|
>






|
>


|

|
>



|
>

|
|
>


|
>

|
|

|
>


|
|

|
>



|
>










|








|
>




|
|
>



|
>

|
|
>


|
|
|
>


<
|
>

|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
|
>




|
>

>

|


>
|

>
>






|
>











|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|








|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|







|
|












|
|

|
>

|
|
>


|
|



|
|

|
>

|
|
>


|
|

|
>






|
|
|
>
|
|
|







|






|
>

|
|
>

|

|
>

|
|
|
>


|


|






|
|

|
>

|
|
>


|
|





|
|
|
>
|
|
|





|
|










|
>

|
|






|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>







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
    #	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 :
  tcl_checkSocket=0
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 :

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.
   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 (void);
int
main (void)
{
return setsockopt ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_socket_setsockopt=yes
else case e in #(
  e) ac_cv_lib_socket_setsockopt=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 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 :
  tcl_checkNsl=0
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 :

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.
   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 (void);
int
main (void)
{
return gethostbyname ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_nsl_gethostbyname=yes
else case e in #(
  e) ac_cv_lib_nsl_gethostbyname=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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



printf "%s\n" "#define _REENTRANT 1" >>confdefs.h


printf "%s\n" "#define _THREAD_SAFE 1" >>confdefs.h

    { 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.
   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 (void);
int
main (void)
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_pthread_pthread_mutex_init=yes
else case e in #(
  e) ac_cv_lib_pthread_pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 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]
	{ 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.
   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 (void);
int
main (void)
{
return __pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_pthread___pthread_mutex_init=yes
else case e in #(
  e) ac_cv_lib_pthread___pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 case e in #(
  e) tcl_ok=no ;;
esac
fi

    fi

    if test "$tcl_ok" = "yes"; then
	# The space is needed
	THREADS_LIBS=" -lpthread"
    else
	{ 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.
   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 (void);
int
main (void)
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_pthreads_pthread_mutex_init=yes
else case e in #(
  e) ac_cv_lib_pthreads_pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 case e in #(
  e) tcl_ok=no ;;
esac
fi

	if test "$tcl_ok" = "yes"; then
	    # The space is needed
	    THREADS_LIBS=" -lpthreads"
	else
	    { 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.
   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 (void);
int
main (void)
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_c_pthread_mutex_init=yes
else case e in #(
  e) ac_cv_lib_c_pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 case e in #(
  e) tcl_ok=no ;;
esac
fi

	    if test "$tcl_ok" = "no"; then
		{ 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.
   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 (void);
int
main (void)
{
return pthread_mutex_init ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_c_r_pthread_mutex_init=yes
else case e in #(
  e) ac_cv_lib_c_r_pthread_mutex_init=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 case e in #(
  e) tcl_ok=no ;;
esac
fi

		if test "$tcl_ok" = "yes"; then
		    # The space is needed
		    THREADS_LIBS=" -pthread"
		else
		    { 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"
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



fi


    LIBS=$ac_saved_libs

    # TIP #509
    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 case e in #(
  e) ac_have_decl=0 ;;
esac
fi


printf "%s\n" "#define HAVE_DECL_PTHREAD_MUTEX_RECURSIVE $ac_have_decl" >>confdefs.h

if test $ac_have_decl = 1
then :
  tcl_ok=yes
else case e in #(
  e) tcl_ok=no ;;
esac
fi



# Add the threads support libraries
LIBS="$LIBS$THREADS_LIBS"


    { 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+y}
then :
  enableval=$enable_shared; tcl_ok=$enableval
else case e in #(
  e) tcl_ok=yes ;;

esac






fi

    if test "$tcl_ok" = "yes" ; then
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared" >&5
printf "%s\n" "shared" >&6; }
	SHARED_BUILD=1
    else
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static" >&5
printf "%s\n" "static" >&6; }
	SHARED_BUILD=0

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.
#--------------------------------------------------------------------


    { 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"
	{ 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=""
	{ 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_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 :

else case e in #(
  e) zlib_ok=no ;;
esac
fi

else case e in #(
  e)
  zlib_ok=no ;;
esac
fi


if test $zlib_ok = yes
then :

  { 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.
   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 (void);
int
main (void)
{
return deflateSetHeader ();
  ;
  return 0;
}
_ACEOF
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 :
  ac_cv_search_deflateSetHeader=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext
  if test ${ac_cv_search_deflateSetHeader+y}
then :
  break
fi
done
if test ${ac_cv_search_deflateSetHeader+y}
then :

else case e in #(
  e) ac_cv_search_deflateSetHeader=no ;;
esac
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS ;;
esac
fi
{ 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 :
  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"

else case e in #(
  e)
    zlib_ok=no
   ;;
esac
fi

fi
if test $zlib_ok = no
then :

  ZLIB_OBJS=\${ZLIB_OBJS}

  ZLIB_SRCS=\${ZLIB_SRCS}

  ZLIB_INCLUDE=-I\${ZLIB_DIR}


fi

printf "%s\n" "#define HAVE_ZLIB 1" >>confdefs.h


#------------------------------------------------------------------------
#	Add stuff for libtommath

libtommath_ok=yes

# Check whether --with-system-libtommath was given.
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_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 :

else case e in #(
  e) libtommath_ok=no ;;
esac
fi

else case e in #(
  e)
	libtommath_ok=no ;;
esac
fi


    if test $libtommath_ok = yes
then :

	{ 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.
   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 (void);
int
main (void)
{
return mp_log_u32 ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_tommath_mp_log_u32=yes
else case e in #(
  e) ac_cv_lib_tommath_mp_log_u32=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 case e in #(
  e)
    libtommath_ok=no ;;
esac
fi

fi
fi
if test $libtommath_ok = yes
then :

  TCL_PC_REQUIRES_PRIVATE='libtommath >= 1.2.0,'

  TCL_PC_CFLAGS='-DTCL_WITH_EXTERNAL_TOMMATH'


printf "%s\n" "#define TCL_WITH_EXTERNAL_TOMMATH 1" >>confdefs.h


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
{ 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 #(((
    '') 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_RANLIB="${ac_tool_prefix}ranlib"
    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
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
printf "%s\n" "$RANLIB" >&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_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
{ 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 #(((
    '') 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_RANLIB="ranlib"
    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_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
  { 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:)
{ 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?

    { 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+y}
then :
  enableval=$enable_64bit; do64bit=$enableval
else case e in #(
  e) do64bit=no ;;
esac
fi

    { 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?

    { 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+y}
then :
  enableval=$enable_64bit_vis; do64bitVIS=$enableval
else case e in #(
  e) do64bitVIS=no ;;
esac
fi

    { 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 :
  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.

    { 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 (void)
{
f();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cc_visibility_hidden=yes
else case e in #(
  e) tcl_cv_cc_visibility_hidden=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_visibility_hidden" >&5
printf "%s\n" "$tcl_cv_cc_visibility_hidden" >&6; }
    if test $tcl_cv_cc_visibility_hidden = yes
then :


printf "%s\n" "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h


printf "%s\n" "#define HAVE_HIDDEN 1" >>confdefs.h


fi

    # Step 0.d: Disable -rpath support?

    { 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+y}
then :
  enableval=$enable_rpath; doRpath=$enableval
else case e in #(
  e) doRpath=yes ;;
esac
fi

    { 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.


    { 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
		{ 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
{ 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.

    { 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.
   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 (void);
int
main (void)
{
return dlopen ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_dl_dlopen=yes
else case e in #(
  e) ac_cv_lib_dl_dlopen=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 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
    # 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 :


	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"
		;;
	esac


else

	CFLAGS_OPTIMIZE=-O
	CFLAGS_WARNING=""


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
  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

  test -z "$as_dir" && as_dir=.



    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_AR="${ac_tool_prefix}ar"
    $as_echo "$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
AR=$ac_cv_prog_AR
if test -n "$AR"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
$as_echo "$AR" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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_AR="ar"
    $as_echo "$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
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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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;}
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 :

  SHLIB_VERSION="1.0"
fi
    case $system in
	AIX-*)
	    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/'`
			;;
		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; }

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 "$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;}

else

		    do64bit_ok=yes
		    CFLAGS="$CFLAGS -q64"
		    LDFLAGS_ARCH="-q64"
		    RANLIB="${RANLIB} -X64"
		    AR="${AR} -X64"
		    SHLIB_LD_FLAGS="-b64"


fi

fi

	    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 :


		    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'

else

		    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'


fi
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'

else

		if test "$GCC" = yes; then :


		    SHLIB_LD='${CC} -shared -Wl,-bexpall'

else

		    SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
		    LDFLAGS="$LDFLAGS -brtl"


fi
		SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
		DL_LIBS="-ldl"
		CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}


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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char inet_ntoa ();
int
main ()
{
return inet_ntoa ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_bind_inet_ntoa=yes
else
  ac_cv_lib_bind_inet_ntoa=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  LIBS="$LIBS -lbind -lsocket"
fi

	    ;;
	BSD/OS-2.1*|BSD/OS-3*)
	    SHLIB_CFLAGS=""
	    SHLIB_LD="shlicc -r"







|
>







|




|
|


|
>




|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|








|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|







|
|













|
>




|
>











|
|














|
>

|
>

|
|

|
|






|
>




|
>





|
>



|
|

|
>



|
|
|
>



|
|


|
>





|
>














|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>







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
    # 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 :

	CFLAGS_OPTIMIZE=-O2
	CFLAGS_WARNING="-Wall -Wextra -Wshadow -Wundef -Wwrite-strings -Wpointer-arith"
	case "${CC}" in
	    *++|*++-*)
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -fextended-identifiers"
		;;
	esac


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
{ 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 #(((
    '') 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_AR="${ac_tool_prefix}ar"
    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
AR=$ac_cv_prog_AR
if test -n "$AR"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
printf "%s\n" "$AR" >&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_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
{ 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 #(((
    '') 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_AR="ar"
    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_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
printf "%s\n" "$ac_ct_AR" >&6; }
else
  { 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:)
{ 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 :
  SHLIB_VERSION="1.0"
fi
    case $system in
	AIX-*)
	    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/'`
			;;
		esac
		{ 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 "$GCC" = yes
then :

		    { 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 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 :

		# 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 :

		    CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'

else case e in #(
  e)
		    CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
		 ;;
esac
fi
		LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'

else case e in #(
  e)
		if test "$GCC" = yes
then :

		    SHLIB_LD='${CC} -shared -Wl,-bexpall'

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.
	    #-----------------------------------------------------------
	    { 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.
   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 (void);
int
main (void)
{
return inet_ntoa ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_bind_inet_ntoa=yes
else case e in #(
  e) ac_cv_lib_bind_inet_ntoa=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*)
	    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,\[email protected]"
	    { $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
/* end confdefs.h.  */

		#ifdef __CYGWIN__
		    #error cygwin
		#endif

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  ac_cv_cygwin=no
else
  ac_cv_cygwin=yes

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cygwin" >&5
$as_echo "$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"
		# The eval makes quoting arguments work.
		if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix
		then :
		else
		    { echo "configure: error: configure failed for ../win" 1>&2; exit 1; }
		fi
	    fi
	    ;;
	dgux*)







|









<
<
<
|
|
|
>
|
|
|







|






|
>

|
|
>

|
|
>

|
|





|

|







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
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	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=""



	    { 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_cygwin=no
else case e in #(
  e) ac_cv_cygwin=yes ;;
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_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 --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 --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
	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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char inet_ntoa ();
int
main ()
{
return inet_ntoa ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_network_inet_ntoa=yes
else
  ac_cv_lib_network_inet_ntoa=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  LIBS="$LIBS -lnetwork"
fi

	    ;;
	HP-UX-*.11.*)
	    # Use updated header definitions where possible

$as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h


$as_echo "#define _XOPEN_SOURCE 1" >>confdefs.h

	    LIBS="$LIBS -lxnet"               # Use the XOPEN network library

	    if test "`uname -m`" = ia64; then :


		SHLIB_SUFFIX=".so"

else

		SHLIB_SUFFIX=".sl"


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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char shl_load ();
int
main ()
{
return shl_load ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_dld_shl_load=yes
else
  ac_cv_lib_dld_shl_load=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  tcl_ok=yes
else
  tcl_ok=no

fi

	    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 :


		SHLIB_LD='${CC} -shared'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}

else

		CFLAGS="$CFLAGS -z"


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 "$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 :


				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;}
			    ;;
		    esac

else

		    do64bit_ok=yes
		    CFLAGS="$CFLAGS +DD64"
		    LDFLAGS_ARCH="+DD64"


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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char shl_load ();
int
main ()
{
return shl_load ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_dld_shl_load=yes
else
  ac_cv_lib_dld_shl_load=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  tcl_ok=yes
else
  tcl_ok=no

fi

	    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"







|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>







|


|



|
>



|
|

|
>

|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>


|
>











|
>




|
|

|
>






|
>

|
>






|
>






|
|



|
|



|
>





|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>


|
>







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
	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"
	    { 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.
   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 (void);
int
main (void)
{
return inet_ntoa ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_network_inet_ntoa=yes
else case e in #(
  e) ac_cv_lib_network_inet_ntoa=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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

printf "%s\n" "#define _XOPEN_SOURCE_EXTENDED 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 :

		SHLIB_SUFFIX=".so"

else case e in #(
  e)
		SHLIB_SUFFIX=".sl"
	     ;;
esac
fi
	    { 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.
   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 (void);
int
main (void)
{
return shl_load ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_dld_shl_load=yes
else case e in #(
  e) ac_cv_lib_dld_shl_load=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 case e in #(
  e) tcl_ok=no ;;
esac
fi

	    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 :

		SHLIB_LD='${CC} -shared'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}

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 "$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 :

				CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
			    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
			    ;;
			*)
			    { 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 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"
	    { 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.
   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 (void);
int
main (void)
{
return shl_load ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_dld_shl_load=yes
else case e in #(
  e) ac_cv_lib_dld_shl_load=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 case e in #(
  e) tcl_ok=no ;;
esac
fi

	    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
	    DL_LIBS=""
	    case " $LIBOBJS " in
  *" mkstemp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
 ;;
esac

	    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 :


		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
	    if test "$GCC" = yes; then :


		CFLAGS="$CFLAGS -mabi=n32"
		LDFLAGS="$LDFLAGS -mabi=n32"

else

		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"


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 :


		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 "$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;}

else

	            do64bit_ok=yes
	            SHLIB_LD="ld -64 -shared -rdata_shared"
	            CFLAGS="$CFLAGS -64"
	            LDFLAGS_ARCH="-64"


fi

fi
	    ;;
	Linux*|GNU*|NetBSD-Debian)
	    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"










	    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 :

  CFLAGS="$CFLAGS -mieee"
fi
	    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

		    hold_cflags=$CFLAGS
		    CFLAGS="$CFLAGS -m64"
		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_cc_m64=yes
else
  tcl_cv_cc_m64=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
		    CFLAGS=$hold_cflags

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 :


		    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 :

  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 :


		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 :


		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"







|
>

















|
>




|
>




|
|










|
>














|
>







|
>

|
>

|
|

|
|




|
>




|













>
>
>
>
>
>
>
>
>
>
|
>




|
>


|
>

|
|
|
>
|
|
|






|






|
>

|
|
>

|

|
>

|
|
|
>














|
>











|
>



















|
>







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
	    DL_LIBS=""
	    case " $LIBOBJS " in
  *" mkstemp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
 ;;
esac

	    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 :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
	    if test "$GCC" = yes
then :

		CFLAGS="$CFLAGS -mabi=n32"
		LDFLAGS="$LDFLAGS -mabi=n32"

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 :

		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 "$GCC" = yes
then :

	            { 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 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|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 :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
fi
	    LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
	    if test "`uname -m`" = "alpha"
then :
  CFLAGS="$CFLAGS -mieee"
fi
	    if test $do64bit = yes
then :

		{ 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cc_m64=yes
else case e in #(
  e) tcl_cv_cc_m64=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_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 :
  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 :

		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 :

		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
	    # 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 :


		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"
	    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 :


		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











































			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_cc_arch_ppc64=yes
else
  tcl_cv_cc_arch_ppc64=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
			    CFLAGS=$hold_cflags

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 :


			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    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

			    hold_cflags=$CFLAGS
			    CFLAGS="$CFLAGS -arch x86_64"
			    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  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

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
			    CFLAGS=$hold_cflags

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 :


			    CFLAGS="$CFLAGS -arch x86_64"
			    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;};;
		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 ()
{
int i;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_ld_single_module=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"

fi
	    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

		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{
int i;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_ld_search_paths_first=yes
else
  tcl_cv_ld_search_paths_first=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_search_paths_first" >&5
$as_echo "$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 :



$as_echo "#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"

$as_echo "#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; }
	    # Check whether --enable-corefoundation was given.
if test "${enable_corefoundation+set}" = set; then :

  enableval=$enable_corefoundation; tcl_corefoundation=$enableval
else
  tcl_corefoundation=yes

fi

	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_corefoundation" >&5
$as_echo "$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

		    hold_libs=$LIBS
		    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 ()
{
CFBundleRef b = CFBundleGetMainBundle();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_lib_corefoundation=yes
else
  tcl_cv_lib_corefoundation=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
		    if test "$fat_32_64" = yes; then :


			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
		        done
fi
		    LIBS=$hold_libs

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 :


		    LIBS="$LIBS -framework CoreFoundation"

$as_echo "#define HAVE_COREFOUNDATION 1" >>confdefs.h


else
  tcl_corefoundation=no

fi
		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

			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 ()
{
CFBundleRef b = CFBundleGetMainBundle();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_lib_corefoundation_64=yes
else
  tcl_cv_lib_corefoundation_64=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
			done

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 :



$as_echo "#define NO_COREFOUNDATION_64 1" >>confdefs.h

                        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

	    ;;
	OSF1-V*)
	    # Digital OSF/1
	    SHLIB_CFLAGS=""
	    if test "$SHARED_BUILD" = 1; then :


	        SHLIB_LD='ld -shared -expect_unresolved "*"'

else

	        SHLIB_LD='ld -non_shared -expect_unresolved "*"'


fi
	    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='-rpath ${LIB_RUNTIME_DIR}'
fi
	    if test "$GCC" = yes; then :

  CFLAGS="$CFLAGS -mieee"
else

		CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"

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 :


		LIBS="$LIBS -lpthread -lmach -lexc"

else

		CFLAGS="$CFLAGS -pthread"
		LDFLAGS="$LDFLAGS -pthread"


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 :


		SHLIB_CFLAGS="-fPIC -melf"
		LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"

else

		SHLIB_CFLAGS="-Kpic -belf"
		LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"


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


$as_echo "#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 :


		SHLIB_LD='${CC} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}

else

		SHLIB_LD="/usr/ccs/bin/ld -G -z text"
		CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}


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


$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h


	    SHLIB_CFLAGS="-KPIC"

	    # Check to enable 64-bit flags for compiler/linker
	    if test "$do64bit" = yes; then :


		arch=`isainfo`
		if test "$arch" = "sparcv9 sparc"; then :


		    if test "$GCC" = yes; 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;}

else

			    do64bit_ok=yes
			    CFLAGS="$CFLAGS -m64 -mcpu=v9"
			    LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
			    SHLIB_CFLAGS="-fPIC"


fi

else

			do64bit_ok=yes
			if test "$do64bitVIS" = yes; then :


			    CFLAGS="$CFLAGS -xarch=v9a"
			    LDFLAGS_ARCH="-xarch=v9a"

else

			    CFLAGS="$CFLAGS -xarch=v9"
			    LDFLAGS_ARCH="-xarch=v9"


fi
			# Solaris 64 uses this as well
			#LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"


fi

else
  if test "$arch" = "amd64 i386"; 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;};;
			esac

else

			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


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

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 :

  use_sunmath=no
else

		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 :


			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "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 :


fi


			use_sunmath=yes

else

			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
			use_sunmath=no


fi


fi
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    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 "$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 :


			SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"

fi

fi

fi

else

		if test "$use_sunmath" = yes; then :

  textmode=textoff
else
  textmode=text

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}'


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

		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{
int i;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_ld_Bexport=yes
else
  tcl_cv_ld_Bexport=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_Bexport" >&5
$as_echo "$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 :


	{ $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;}

fi

    if test "$do64bit" = yes -a "$do64bit_ok" = yes; then :



$as_echo "#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 :

  enableval=$enable_load; tcl_ok=$enableval
else
  tcl_ok=yes

fi

    if test "$tcl_ok" = no; then :

  DL_OBJS=""
fi

    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;}
	SHLIB_CFLAGS=""
	SHLIB_LD=""
	SHLIB_SUFFIX=""
	DL_OBJS="tclLoadNone.o"
	DL_LIBS=""
	LDFLAGS="$LDFLAGS_ORIG"
	CC_SEARCH_FLAGS=""
	LD_SEARCH_FLAGS=""
	BUILD_DLTEST=""


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 :


	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*) ;;
	    HP_UX*) ;;
	    Darwin-*) ;;
	    IRIX*) ;;
	    Linux*|GNU*) ;;
	    NetBSD-*|OpenBSD-*) ;;
	    OSF1-V*) ;;
	    SCO_SV-3.2*) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac
fi

    if test "$tcl_cv_cc_visibility_hidden" != yes; then :



$as_echo "#define MODULE_SCOPE extern" >>confdefs.h


fi

    if test "$SHARED_LIB_SUFFIX" = ""; then :


	SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'
fi
    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 :


        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)"

else

            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'


fi

else

        LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}

        if test "$RANLIB" = ""; then :


            MAKE_LIB='$(STLIB_LD) $@ ${OBJS}'

else

            MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@'


fi
        INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'


fi

    # Stub lib does not depend on shared/static configuration
    if test "$RANLIB" = ""; then :


        MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}'

else

        MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@'


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 :


        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.

	{ $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
/* end confdefs.h.  */

int
main ()
{

		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_cast_to_union=yes
else
  tcl_cv_cast_to_union=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


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























































$as_echo "#define HAVE_CAST_TO_UNION 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 :


$as_echo "#define HAVE_STDBOOL_H 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.









|
>









<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|










|
>



|
|
|
>
|
|
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|




|






|
>
|
|
|
>

|

|
>

|
|
|
>

|



|
|
|
|
>
|
|
|

|




|






|
>
|
|
|
>

|

|
>

|
|
|
>

|




|
|


|
|

|
|
>



|
>


|
|
|
>
|
|
|






|






|
>

|
|
>

|

|
>

|
|
|
>








|
|
|
>
|
|
|






|






|
>

|
|
>

|

|
>

|
|
|
>




|
>


|






|

|



|
|

|
>

|
|
>


|
|
|
>

|
|
|
>
|
|
|

|
>














|






|
>

|
|
>

|

|
>





|
>

|
|
|
>



|


|
|
>

|
>

|
|
|
>
|
|
|







|






|
>

|
|
>

|



|
>

|
|
|
>


|













|





|
>

|

|
|
|
|
>




|
>




|
>

|
|
|
>





|
>



|
|


|
>


















|
>




|
|


|
>
















|


|






|
>





|
|



|
>







|


|





|
>


|
>

|
>

|
>

|
|

|
|




|
>


|
|

|
>




|
|


|
>



|
>


|
|
>

|
>







|
|


|
|









|
>


|
|
|
>
|
>








|
>

|
|

|
|
|
>

|
|

|
|
>


<



|
|
|
|

|
>

|
>




|
>




|
>

|
>









|
|
>



|
>




|
|
|
>

|
|
>









|
>











|
|
|
>
|
|
|






|






|
>

|
|
>

|

|
>

|
|
|
>









|
>

|
|



|
>


|









|
>

|
|
>


|
>



|
>

|
|
|
|









|
>







|
>




|
|




|





|
>


|




|
>



|
>





|
>



|
>

|


|
|

|
>


|
|


|
>



|
|

|
>


|
>



|
>



|
|

|
>






|
>





|
|
|

|
|
|
>
|
|
|



|


|
|





|
>

|
|
>

|
|
>

|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>

|
|
>

|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	    # 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 :

		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"
	    ;;


























	Darwin-*)
	    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 :

		case `arch` in
		    ppc)
			{ 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 x86_64"
			    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_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 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_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 x86_64"
			    do64bit_ok=yes

fi;;
		    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 arm64"
			    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_arm64=yes
else case e in #(
  e) tcl_cv_cc_arch_arm64=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_arm64" >&5
printf "%s\n" "$tcl_cv_cc_arch_arm64" >&6; }
			if test $tcl_cv_cc_arch_arm64 = yes
then :

			    CFLAGS="$CFLAGS -arch arm64"
			    do64bit_ok=yes

fi;;
		    *)
			{ 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 case e in #(
  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 :

		    fat_32_64=yes
fi
	     ;;
esac
fi
	    SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}'
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5
printf %s "checking if ld accepts -single_module flag... " >&6; }
if test ${tcl_cv_ld_single_module+y}
then :
  printf %s "(cached) " >&6
else case e in #(
  e)
		hold_ldflags=$LDFLAGS
		LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{
int i;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_ld_single_module=yes
else case e in #(
  e) tcl_cv_ld_single_module=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
		LDFLAGS=$hold_ldflags ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5
printf "%s\n" "$tcl_cv_ld_single_module" >&6; }
	    if test $tcl_cv_ld_single_module = yes
then :

		SHLIB_LD="${SHLIB_LD} -Wl,-single_module"

fi
	    SHLIB_SUFFIX=".dylib"
	    DL_OBJS="tclLoadDyld.o"
	    DL_LIBS=""
	    LDFLAGS="$LDFLAGS -headerpad_max_install_names"
	    { 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 (void)
{
int i;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_ld_search_paths_first=yes
else case e in #(
  e) tcl_cv_ld_search_paths_first=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
		LDFLAGS=$hold_ldflags ;;
esac
fi
{ 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 :


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_FALLBACK_LIBRARY_PATH"

printf "%s\n" "#define MAC_OSX_TCL 1" >>confdefs.h

	    PLAT_OBJS='${MAC_OSX_OBJS}'
	    PLAT_SRCS='${MAC_OSX_SRCS}'
	    { 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+y}
then :
  enableval=$enable_corefoundation; tcl_corefoundation=$enableval
else case e in #(
  e) tcl_corefoundation=yes ;;
esac
fi

	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_corefoundation" >&5
printf "%s\n" "$tcl_corefoundation" >&6; }
	    if test $tcl_corefoundation = yes
then :

		{ 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 :

			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 (void)
{
CFBundleRef b = CFBundleGetMainBundle();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_lib_corefoundation=yes
else case e in #(
  e) tcl_cv_lib_corefoundation=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
		    if test "$fat_32_64" = yes
then :

			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
		        done
fi
		    LIBS=$hold_libs ;;
esac
fi
{ 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"

printf "%s\n" "#define HAVE_COREFOUNDATION 1" >>confdefs.h


else case e in #(
  e) tcl_corefoundation=no ;;
esac
fi
		if test "$fat_32_64" = yes -a $tcl_corefoundation = yes
then :

		    { 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 (void)
{
CFBundleRef b = CFBundleGetMainBundle();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_lib_corefoundation_64=yes
else case e in #(
  e) tcl_cv_lib_corefoundation_64=no ;;
esac
fi
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 ;;
esac
fi
{ 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 :


printf "%s\n" "#define NO_COREFOUNDATION_64 1" >>confdefs.h

                        LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings"

fi

fi

fi
	    ;;
	OS/390-*)
	    SHLIB_LD_LIBS=""
	    CFLAGS_OPTIMIZE=""		# Optimizer is buggy

printf "%s\n" "#define _OE_SOCKETS 1" >>confdefs.h

	    ;;
	OSF1-V*)
	    # Digital OSF/1
	    SHLIB_CFLAGS=""
	    if test "$SHARED_BUILD" = 1
then :

	        SHLIB_LD='${CC} -shared'

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 :

		CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"'
		LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
fi
	    if test "$GCC" = yes
then :
  CFLAGS="$CFLAGS -mieee"
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 :

		LIBS="$LIBS -lpthread -lmach -lexc"

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 :

		SHLIB_CFLAGS="-fPIC -melf"
		LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"

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.


printf "%s\n" "#define _REENTRANT 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 :

		SHLIB_LD='${CC} -shared'
		CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
		LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}

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.


printf "%s\n" "#define _REENTRANT 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 :

		arch=`isainfo`
		if test "$arch" = "sparcv9 sparc"
then :

		    if test "$GCC" = yes
then :

			if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3
then :

			    { 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 case e in #(
  e)
			    do64bit_ok=yes
			    CFLAGS="$CFLAGS -m64 -mcpu=v9"
			    LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
			    SHLIB_CFLAGS="-fPIC"
			 ;;
esac
fi

else case e in #(
  e)
			do64bit_ok=yes
			if test "$do64bitVIS" = yes
then :

			    CFLAGS="$CFLAGS -xarch=v9a"
			    LDFLAGS_ARCH="-xarch=v9a"

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 case e in #(
  e) if test "$arch" = "amd64 i386"
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";;
			    *)
				{ 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 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 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 :
  use_sunmath=no
else case e in #(
  e)
		arch=`isainfo`
		{ 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 :

			{ 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_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 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 :

		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 "$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 case e in #(
  e) if test "$arch" = "amd64 i386"
then :

			SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"

fi ;;
esac
fi

fi

else case e in #(
  e)
		if test "$use_sunmath" = yes
then :
  textmode=textoff
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.
	    { 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 (void)
{
int i;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_ld_Bexport=yes
else case e in #(
  e) tcl_cv_ld_Bexport=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
	        LDFLAGS=$hold_ldflags ;;
esac
fi
{ 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 :

	{ 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 :


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+y}
then :
  enableval=$enable_load; tcl_ok=$enableval
else case e in #(
  e) tcl_ok=yes ;;
esac
fi

    if test "$tcl_ok" = no
then :
  DL_OBJS=""
fi

    if test "x$DL_OBJS" != x
then :
  BUILD_DLTEST="\$(DLTEST_TARGETS)"
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 :

	case $system in
	    AIX-*) ;;
	    BSD/OS*) ;;
	    CYGWIN_*|MINGW32_*|MSYS_*) ;;
	    HP-UX*) ;;
	    Darwin-*) ;;
	    IRIX*) ;;
	    Linux*|GNU*) ;;
	    NetBSD-*|OpenBSD-*) ;;
	    OSF1-*) ;;
	    SCO_SV-3.2*) ;;
	    *) SHLIB_CFLAGS="-fPIC" ;;
	esac
fi

    if test "$tcl_cv_cc_visibility_hidden" != yes
then :


printf "%s\n" "#define MODULE_SCOPE extern" >>confdefs.h


fi

    if test "$SHARED_LIB_SUFFIX" = ""
then :

	SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}'
fi
    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 :

        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)"'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"

else case e in #(
  e)
            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
         ;;
esac
fi

else case e in #(
  e)
        LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}

        if test "$RANLIB" = ""
then :

            MAKE_LIB='$(STLIB_LD) $@ ${OBJS}'

else case e in #(
  e)
            MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@'
         ;;
esac
fi
        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 :

        MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}'

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 :

        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.

    { 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 (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 :
  tcl_cv_cast_to_union=yes
else case e in #(
  e) tcl_cv_cast_to_union=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_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)
{

  ;
  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_compile "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default"
if test "x$ac_cv_header_stdbool_h" = xyes
then :

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







cat >>confdefs.h <<_ACEOF
#define TCL_SHLIB_EXT "${SHLIB_SUFFIX}"
_ACEOF











    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5
$as_echo_n "checking for build with symbols... " >&6; }
    # Check whether --enable-symbols was given.
if test "${enable_symbols+set}" = set; then :

  enableval=$enable_symbols; tcl_ok=$enableval
else
  tcl_ok=no

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

	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }

$as_echo "#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; }
	fi
    fi



    if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then

$as_echo "#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


$as_echo "#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; }
	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
$as_echo "enabled $tcl_ok debugging" >&6; }
	fi
    fi



$as_echo "#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; }
    tcl_flags=""

    if ${tcl_cv_flag__isoc99_source+:} false; then :

  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <stdlib.h>
int
main ()
{
char *p = (char *)strtoll; char *q = (char *)strtoull;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_flag__isoc99_source=no
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#define _ISOC99_SOURCE 1
#include <stdlib.h>
int
main ()
{
char *p = (char *)strtoll; char *q = (char *)strtoull;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_flag__isoc99_source=yes
else
  tcl_cv_flag__isoc99_source=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__isoc99_source}" = "xyes" ; then

$as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h

	tcl_flags="$tcl_flags _ISOC99_SOURCE"
    fi























































    if ${tcl_cv_flag__largefile64_source+:} false; then :

  $as_echo_n "(cached) " >&6
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/stat.h>
int
main ()
{
struct stat64 buf; int i = stat64("/", &buf);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_flag__largefile64_source=no
else
  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#define _LARGEFILE64_SOURCE 1
#include <sys/stat.h>
int
main ()
{
struct stat64 buf; int i = stat64("/", &buf);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_flag__largefile64_source=yes
else
  tcl_cv_flag__largefile64_source=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__largefile64_source}" = "xyes" ; then

$as_echo "#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; }
    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5
$as_echo "${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

	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
/* end confdefs.h.  */

int
main ()
{
switch (0) {
            case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ;
        }
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_type_64bit=${tcl_type_64bit}
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi

    if test "${tcl_cv_type_64bit}" = none ; then

$as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h

	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "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
$as_echo "${tcl_cv_type_64bit}" >&6; }

	# Now check for auxiliary declarations







































































	{ $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

	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
#include <dirent.h>
int
main ()
{
struct dirent64 p;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_struct_dirent64=yes
else
  tcl_cv_struct_dirent64=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5
$as_echo "$tcl_cv_struct_dirent64" >&6; }
	if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then

$as_echo "#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

	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
#include <dirent.h>
int
main ()
{
struct dirent64 *p; DIR64 d = opendir64(".");
            p = readdir64(d); rewinddir64(d); closedir64(d);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_DIR64=yes
else
  tcl_cv_DIR64=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5
$as_echo "$tcl_cv_DIR64" >&6; }
	if test "x${tcl_cv_DIR64}" = "xyes" ; then

$as_echo "#define HAVE_DIR64 1" >>confdefs.h

	fi

	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5
$as_echo_n "checking for struct stat64... " >&6; }
if ${tcl_cv_struct_stat64+:} false; then :
  $as_echo_n "(cached) " >&6
else

	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/stat.h>
int
main ()
{
struct stat64 p;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  tcl_cv_struct_stat64=yes
else
  tcl_cv_struct_stat64=no
fi




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

	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

	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
int
main ()
{
off64_t offset;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_type_off64_t=yes
else
  tcl_cv_type_off64_t=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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

$as_echo "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h

	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
    # 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 :


	# 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







|
|
<











|
|

|
>

|
|
>







|

|
|

|





|
|







|





|


|





|
|

|
|





|







|
|


|
>
|
|
|



|






|
>

|
|




|






|
>

|
|
>

|
>

|
>




|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
|



|






|
>

|
|




|






|
>

|
|
>

|
>

|
>




|




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
|

|
|




|
|
|
>
|
|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







|


|





|
>
|

|
>




|

|
|

<
<
<
<
<
|
<
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
|
|
|





|






|
>

|
|
>

|
>

|
|


|



|
|
|
>
|
|
|





|







|
>

|
|
>

|
>

|
|


|



|
<
<
<
<
|
<
<
<
<
|
<
<
|
|
<
<
<
<
<
<
<

>
>
>
>
<
<
<
<
<

<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
>
|
|
|




|







|
>

|
|
>

|
>






|

|
|

|
|









|
|
|
>
|
|
|









|
>







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








printf "%s\n" "#define TCL_SHLIB_EXT \"${SHLIB_SUFFIX}\"" >>confdefs.h












    { 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+y}
then :
  enableval=$enable_symbols; tcl_ok=$enableval
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)'

printf "%s\n" "#define NDEBUG 1" >>confdefs.h

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }

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
	    { 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

printf "%s\n" "#define TCL_MEM_DEBUG 1" >>confdefs.h

    fi

    	if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then

printf "%s\n" "#define TCL_COMPILE_DEBUG 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
	    { 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
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
printf "%s\n" "enabled $tcl_ok debugging" >&6; }
	fi
    fi



printf "%s\n" "#define MP_PREC 4" >>confdefs.h


#--------------------------------------------------------------------
#	Detect what compiler flags to set for 64-bit support.
#--------------------------------------------------------------------


    { 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 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 (void)
{
char *p = (char *)strtoll; char *q = (char *)strtoull;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__isoc99_source=no
else case e in #(
  e) cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#define _ISOC99_SOURCE 1
#include <stdlib.h>
int
main (void)
{
char *p = (char *)strtoll; char *q = (char *)strtoull;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__isoc99_source=yes
else case e in #(
  e) tcl_cv_flag__isoc99_source=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__isoc99_source}" = "xyes" ; then

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 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 (void)
{
struct stat64 buf; int i = stat64("/", &buf);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__largefile64_source=no
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 (void)
{
struct stat64 buf; int i = stat64("/", &buf);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_flag__largefile64_source=yes
else case e in #(
  e) tcl_cv_flag__largefile64_source=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__largefile64_source}" = "xyes" ; then

printf "%s\n" "#define _LARGEFILE64_SOURCE 1" >>confdefs.h

	tcl_flags="$tcl_flags _LARGEFILE64_SOURCE"
    fi
















































    if test "x${tcl_flags}" = "x" ; then
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5
printf "%s\n" "none" >&6; }
    else
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5
printf "%s\n" "${tcl_flags}" >&6; }
    fi



    { 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 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
/* end confdefs.h.  */

int
main (void)
{
switch (0) {
            case 1: case (sizeof(long long)==sizeof(long)): ;
        }
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_type_64bit="long long"
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ;;
esac
fi

    if test "${tcl_cv_type_64bit}" = none ; then

printf "%s\n" "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h

	{ 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; }
	# 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

	{ 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 (void)
{
struct dirent64 p;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_struct_dirent64=yes
else case e in #(
  e) tcl_cv_struct_dirent64=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_struct_dirent64" >&5
printf "%s\n" "$tcl_cv_struct_dirent64" >&6; }
	if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then

printf "%s\n" "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h

	fi

	{ 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 (void)
{
struct dirent64 *p; DIR64 d = opendir64(".");
            p = readdir64(d); rewinddir64(d); closedir64(d);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_DIR64=yes
else case e in #(
  e) tcl_cv_DIR64=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_DIR64" >&5
printf "%s\n" "$tcl_cv_DIR64" >&6; }
	if test "x${tcl_cv_DIR64}" = "xyes" ; then

printf "%s\n" "#define HAVE_DIR64 1" >>confdefs.h

	fi

	ac_fn_c_check_func "$LINENO" "open64" "ac_cv_func_open64"




if test "x$ac_cv_func_open64" = xyes




then :


  printf "%s\n" "#define HAVE_OPEN64 1" >>confdefs.h








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








fi













	{ 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 (void)
{
off64_t offset;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_type_off64_t=yes
else case e in #(
  e) tcl_cv_type_off64_t=no ;;
esac
fi
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

printf "%s\n" "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h

	    { 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; }
	fi
    fi


#--------------------------------------------------------------------
#	Check endianness because we can optimize comparisons of
#	Tcl_UniChar strings to memcmp on big-endian systems.
#--------------------------------------------------------------------

 { 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 :

	# 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
	   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
    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 ()
{
#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 :

  # 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 ()
{
#if BYTE_ORDER != BIG_ENDIAN
		 not big endian
		#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  ac_cv_c_bigendian=yes
else
  ac_cv_c_bigendian=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 $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 ()
{
#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
	      bogus endian macros
	     #endif

  ;
  return 0;
}
_ACEOF
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 ()
{
#ifndef _BIG_ENDIAN
		 not big endian
		#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  ac_cv_c_bigendian=yes
else
  ac_cv_c_bigendian=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 $ac_cv_c_bigendian = unknown; then
      # Compile a test program.
      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[] =
		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
		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[] =
		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
		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);
  ;

  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
	      ac_cv_c_bigendian=yes
	    fi
	    if grep LiTTleEnDian conftest.$ac_objext >/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
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{

	     /* 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 :

  ac_cv_c_bigendian=no
else
  ac_cv_c_bigendian=yes

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_c_bigendian" >&5
$as_echo "$ac_cv_c_bigendian" >&6; }
 case $ac_cv_c_bigendian in #(
   yes)
     $as_echo "#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
do :
  ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd"
if test "x$ac_cv_func_getcwd" = xyes; then :
  cat >>confdefs.h <<_ACEOF

#define HAVE_GETCWD 1
_ACEOF

else

$as_echo "#define USEGETWD 1" >>confdefs.h


fi
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

else
  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

else
  case " $LIBOBJS " in
  *" waitpid.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS waitpid.$ac_objext"
 ;;
esac


fi


ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
if test "x$ac_cv_func_strerror" = xyes; then :


else

$as_echo "#define NO_STRERROR 1" >>confdefs.h


fi

ac_fn_c_check_func "$LINENO" "getwd" "ac_cv_func_getwd"
if test "x$ac_cv_func_getwd" = xyes; then :


else

$as_echo "#define NO_GETWD 1" >>confdefs.h


fi

ac_fn_c_check_func "$LINENO" "wait3" "ac_cv_func_wait3"
if test "x$ac_cv_func_wait3" = xyes; then :


else

$as_echo "#define NO_WAIT3 1" >>confdefs.h













fi

ac_fn_c_check_func "$LINENO" "uname" "ac_cv_func_uname"
if test "x$ac_cv_func_uname" = xyes; then :


else









$as_echo "#define NO_UNAME 1" >>confdefs.h
















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 :


else

$as_echo "#define NO_REALPATH 1" >>confdefs.h


fi



	NEED_FAKE_RFC2553=0

	for ac_func in getnameinfo getaddrinfo freeaddrinfo gai_strerror
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

else
  NEED_FAKE_RFC2553=1

fi
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 :


cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_ADDRINFO 1
_ACEOF


else
  NEED_FAKE_RFC2553=1

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 :


cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_IN6_ADDR 1
_ACEOF


else
  NEED_FAKE_RFC2553=1

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 :


cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_SOCKADDR_IN6 1
_ACEOF


else
  NEED_FAKE_RFC2553=1

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 :


cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
_ACEOF


else
  NEED_FAKE_RFC2553=1

fi

if test "x$NEED_FAKE_RFC2553" = "x1"; then

$as_echo "#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 :


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 :


    { $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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <pwd.h>

int
main ()
{

	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 :

  tcl_cv_api_getpwuid_r_5=yes
else
  tcl_cv_api_getpwuid_r_5=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
    tcl_ok=$tcl_cv_api_getpwuid_r_5
    if test "$tcl_ok" = yes; then

$as_echo "#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

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/types.h>
	    #include <pwd.h>

int
main ()
{

	    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 :

  tcl_cv_api_getpwuid_r_4=yes
else
  tcl_cv_api_getpwuid_r_4=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
	tcl_ok=$tcl_cv_api_getpwuid_r_4
	if test "$tcl_ok" = yes; then

$as_echo "#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

    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 :


    { $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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <pwd.h>

int
main ()
{

	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 :

  tcl_cv_api_getpwnam_r_5=yes
else
  tcl_cv_api_getpwnam_r_5=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
    tcl_ok=$tcl_cv_api_getpwnam_r_5
    if test "$tcl_ok" = yes; then

$as_echo "#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

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/types.h>
	    #include <pwd.h>

int
main ()
{

	    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 :

  tcl_cv_api_getpwnam_r_4=yes
else
  tcl_cv_api_getpwnam_r_4=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
	tcl_ok=$tcl_cv_api_getpwnam_r_4
	if test "$tcl_ok" = yes; then

$as_echo "#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

    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 :


    { $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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <grp.h>

int
main ()
{

	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 :

  tcl_cv_api_getgrgid_r_5=yes
else
  tcl_cv_api_getgrgid_r_5=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
    tcl_ok=$tcl_cv_api_getgrgid_r_5
    if test "$tcl_ok" = yes; then

$as_echo "#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

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/types.h>
	    #include <grp.h>

int
main ()
{

	    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 :

  tcl_cv_api_getgrgid_r_4=yes
else
  tcl_cv_api_getgrgid_r_4=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
	tcl_ok=$tcl_cv_api_getgrgid_r_4
	if test "$tcl_ok" = yes; then

$as_echo "#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

    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 :


    { $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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <grp.h>

int
main ()
{

	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 :

  tcl_cv_api_getgrnam_r_5=yes
else
  tcl_cv_api_getgrnam_r_5=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
    tcl_ok=$tcl_cv_api_getgrnam_r_5
    if test "$tcl_ok" = yes; then

$as_echo "#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

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/types.h>
	    #include <grp.h>

int
main ()
{

	    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 :

  tcl_cv_api_getgrnam_r_4=yes
else
  tcl_cv_api_getgrnam_r_4=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
	tcl_ok=$tcl_cv_api_getgrnam_r_4
	if test "$tcl_ok" = yes; then

$as_echo "#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

    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


$as_echo "#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


$as_echo "#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_have_decl=1
else
  ac_have_decl=0

fi

cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GETHOSTBYNAME_R $ac_have_decl
_ACEOF
if test $ac_have_decl = 1; then :


    tcl_cv_api_gethostbyname_r=yes
else
  tcl_cv_api_gethostbyname_r=no

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 :


    { $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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <netdb.h>

int
main ()
{

	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 :

  tcl_cv_api_gethostbyname_r_6=yes
else
  tcl_cv_api_gethostbyname_r_6=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
    tcl_ok=$tcl_cv_api_gethostbyname_r_6
    if test "$tcl_ok" = yes; then

$as_echo "#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

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <netdb.h>

int
main ()
{

	    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 :

  tcl_cv_api_gethostbyname_r_5=yes
else
  tcl_cv_api_gethostbyname_r_5=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
	tcl_ok=$tcl_cv_api_gethostbyname_r_5
	if test "$tcl_ok" = yes; then

$as_echo "#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

	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

		#include <netdb.h>

int
main ()
{

		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 :

  tcl_cv_api_gethostbyname_r_3=yes
else
  tcl_cv_api_gethostbyname_r_3=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
	    tcl_ok=$tcl_cv_api_gethostbyname_r_3
	    if test "$tcl_ok" = yes; then

$as_echo "#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

    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_have_decl=1
else
  ac_have_decl=0

fi

cat >>confdefs.h <<_ACEOF
#define HAVE_DECL_GETHOSTBYADDR_R $ac_have_decl
_ACEOF
if test $ac_have_decl = 1; then :


    tcl_cv_api_gethostbyaddr_r=yes
else
  tcl_cv_api_gethostbyaddr_r=no

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 :


    { $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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <netdb.h>

int
main ()
{

	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 :

  tcl_cv_api_gethostbyaddr_r_7=yes
else
  tcl_cv_api_gethostbyaddr_r_7=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
    tcl_ok=$tcl_cv_api_gethostbyaddr_r_7
    if test "$tcl_ok" = yes; then

$as_echo "#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

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <netdb.h>

int
main ()
{

	    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 :

  tcl_cv_api_gethostbyaddr_r_8=yes
else
  tcl_cv_api_gethostbyaddr_r_8=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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; }
	tcl_ok=$tcl_cv_api_gethostbyaddr_r_8
	if test "$tcl_ok" = yes; then

$as_echo "#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

    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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_TERMIOS_H 1
_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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_SYS_IOCTL_H 1
_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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_SYS_MODEM_H 1
_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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
int
main ()
{
fd_set readMask, writeMask;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_type_fd_set=yes
else
  tcl_cv_type_fd_set=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_fd_set" >&5
$as_echo "$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

	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 :

  tcl_cv_grep_fd_mask=present
else
  tcl_cv_grep_fd_mask=missing

fi
rm -f conftest*


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_fd_mask" >&5
$as_echo "$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

	tcl_ok=yes
    fi
fi
if test $tcl_ok = no; then

$as_echo "#define NO_FD_SET 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; }
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
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
_ACEOF

$as_echo "#define NOTIFIER_EPOLL 1" >>confdefs.h

fi

done

	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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_SYS_EVENTFD_H 1
_ACEOF

$as_echo "#define HAVE_EVENTFD 1" >>confdefs.h

fi

done
;;
  xDragonFlyBSD|xFreeBSD|xNetBSD|xOpenBSD)
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: kqueue(2)" >&5
$as_echo "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
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 :

  cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
_ACEOF
 tcl_kqueue_headers=${tcl_kqueue_headers}y
fi

done

	if test $tcl_kqueue_headers = xyyy; then :



$as_echo "#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; };;
  *)
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
$as_echo "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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_SYS_TIME_H 1
_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)
return 0;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
  ac_cv_header_time=yes
else
  ac_cv_header_time=no
fi




rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
fi
{ $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

fi


    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
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

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 :

  $as_echo_n "(cached) " >&6
else

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end 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

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <time.h>
int
main ()
{
struct tm tm; (void)tm.tm_gmtoff;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_member_tm_gmtoff=yes
else
  tcl_cv_member_tm_gmtoff=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_gmtoff" >&5
$as_echo "$tcl_cv_member_tm_gmtoff" >&6; }
    if test $tcl_cv_member_tm_gmtoff = yes ; then

$as_echo "#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

	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <time.h>

int
main ()
{
extern long timezone;
	    timezone += 1;
	    exit (0);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_timezone_long=yes
else
  tcl_cv_timezone_long=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_long" >&5
$as_echo "$tcl_cv_timezone_long" >&6; }
    if test $tcl_cv_timezone_long = yes ; then

$as_echo "#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

	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <time.h>

int
main ()
{
extern time_t timezone;
		timezone += 1;
		exit (0);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_timezone_time=yes
else
  tcl_cv_timezone_time=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_timezone_time" >&5
$as_echo "$tcl_cv_timezone_time" >&6; }
	if test $tcl_cv_timezone_time = yes ; then

$as_echo "#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 :


cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_BLOCKS 1
_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 :


cat >>confdefs.h <<_ACEOF
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
_ACEOF









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 :


cat >>confdefs.h <<_ACEOF
#define HAVE_BLKCNT_T 1
_ACEOF


fi

ac_fn_c_check_func "$LINENO" "fstatfs" "ac_cv_func_fstatfs"
if test "x$ac_cv_func_fstatfs" = xyes; then :


else

$as_echo "#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 :


else

cat >>confdefs.h <<_ACEOF
#define mode_t int
_ACEOF


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 :


else






cat >>confdefs.h <<_ACEOF



#define pid_t int




_ACEOF













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 :


else

cat >>confdefs.h <<_ACEOF
#define size_t unsigned int
_ACEOF


fi

{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5
$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.  */
#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

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

$as_echo "#define uid_t int" >>confdefs.h



$as_echo "#define gid_t int" >>confdefs.h


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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	#include <sys/types.h>
	#include <sys/socket.h>

int
main ()
{

    	socklen_t foo;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_type_socklen_t=yes
else
  tcl_cv_type_socklen_t=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_type_socklen_t" >&5
$as_echo "$tcl_cv_type_socklen_t" >&6; }
if test $tcl_cv_type_socklen_t = no; then

$as_echo "#define socklen_t int" >>confdefs.h

fi

ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default"
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
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 :


$as_echo "#define HAVE_UINTPTR_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; }
    if test "$tcl_cv_uintptr_t" != none; then

cat >>confdefs.h <<_ACEOF
#define uintptr_t $tcl_cv_uintptr_t
_ACEOF

    fi

fi


#--------------------------------------------------------------------
#	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 :

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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <sys/types.h>
#include <sys/wait.h>
int
main ()
{

union wait x;
WIFEXITED(x);		/* Generates compiler error if WIFEXITED
			 * uses an int. */

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_union_wait=yes
else
  tcl_cv_union_wait=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_union_wait" >&5
$as_echo "$tcl_cv_union_wait" >&6; }
if test $tcl_cv_union_wait = no; then

$as_echo "#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 :

  tcl_ok=1
else
  tcl_ok=0

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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char strncasecmp ();
int
main ()
{
return strncasecmp ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_socket_strncasecmp=yes
else
  ac_cv_lib_socket_strncasecmp=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  tcl_ok=1
else
  tcl_ok=0

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
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.  */



#ifdef __cplusplus
extern "C"
#endif
char strncasecmp ();
int
main ()
{
return strncasecmp ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_lib_inet_strncasecmp=yes
else
  ac_cv_lib_inet_strncasecmp=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS

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 :

  tcl_ok=1
else
  tcl_ok=0

fi

fi
if test "$tcl_ok" = 0; then
    case " $LIBOBJS " in
  *" strncasecmp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS strncasecmp.$ac_objext"







|








|

|
|








|
>







|









|
>

|
|
>

|

|








|









|
>






|









|
>

|
|
>

|

|



|
>



|

|




|

|




<
<
|
|
|
>
>
>
|
<
>
|
|

|
>
|


|








|
>
|
|



|















|
>

|
|
>


|
>


|
>

|
|


|




|
<
<













>
|


|
<
>
|
<

|
|
|
|
>

<

>




|
>
|

|
|




<
<
<
<
<
<
<
<
<
<
<


<

<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
>
|

|
|




|
>


<

|
>

|
|
|
|
>



|
>

|
|
|
|
>



|
>

|
|
|
>
>
>

>
>
>
>
>
>
>
>
>


|
|
>

|
>
>
>
>
>

>
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>










|
>

|
|
|
|
>





>
|

|

|
>

|


|
|
>

<

>







|
>

<
|
<


|
|
>








|
>

<
|
<


|
|
>








|
>

<
|
<


|
|
>








|
>

<
|
<


|
|
>




|








|
>











|
>

|
|
|
>
|
|
|







|













|
>

|
|
>

|
>

|
|



|


|
|
|
>
|
|
|







|













|
>

|
|
>

|
>

|
|



|





|






|
>

|
|
|
>
|
|
|







|













|
>

|
|
>

|
>

|
|



|


|
|
|
>
|
|
|







|













|
>

|
|
>

|
>

|
|



|





|






|
>

|
|
|
>
|
|
|







|













|
>

|
|
>

|
>

|
|



|


|
|
|
>
|
|
|







|













|
>

|
|
>

|
>

|
|



|





|






|
>

|
|
|
>
|
|
|







|













|
>

|
|
>

|
>

|
|



|


|
|
|
>
|
|
|







|













|
>

|
|
>

|
>

|
|



|





|











|


|








|


|





|
|
|
>

|
|
>

<
<
|
<
|
>


|
|
>






|
>

|
|
|
>
|
|
|






|














|
>

|
|
>

|
>

|
|



|


|
|
|
>
|
|
|






|














|
>

|
|
>

|
>

|
|



|


|
|
|
>
|
|
|






|












|
>

|
|
>

|
>

|
|



|






|









|
|
|
>

|
|
>

<
<
|
<
|
>


|
|
>






|
>

|
|
|
>
|
|
|






|

















|
>

|
|
>

|
>

|
|



|


|
|
|
>
|
|
|






|

















|
>

|
|
>

|
>

|
|



|





|


















<
<
|
|
<
>
|
<



<
<
<
<
|
|
<
>
|
<



<
<
<
<
|
|
<
>
|
<


<
<












|
|
|
>
|
|
|




|






|
>

|
|
>

|
>

|
|


|
|
|
>
|
|
|






|
>

|
|
>

|
|
>

|
|


|






|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|
|


|
|
|

|
|
|
|
<

|




<
|

|
|
<
>
|
<

|



|
<

|
|



|

|
|
|
>

|





<
|
>


|





|
|

|
|







|
<
|
|
<
>
|
<



<

<
<
<
<
<
<
<
<
<
<

<
>
>
|
<
>
<
<
|
<
<
<
<
<
<
<

>
>
>
>
|

<
|
|
|
|



<
<
<
<
<
<
<
<
<

<
<
<
<
|
|
|
>
|
|
|




|

|




|
>

|
|
>

|
>

|
|


|



|
|
|
>
|
|
|




|






|
>

|
|
>

|
>

|
|


|







|
|
|
>
|
|
|



>

|








|
>

|
|
>

|
>

|
|


|





|
|
|
>
|
|
|



>

|








|
>

|
|
>

|
>

|
|


|













|
>

<
|
<




|
>

<
|
|
>
>
>
>
>
>
>






|
>

<
|
<





|
>

|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


|









|
>

|
|

|


|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








|
>

|
|
<
|
<
|
>


>
|
>
|
>

|
>
>

>
>
>
|
>
>
>
|
>
>
>
>

>
>
>
>
>
>
>
>

>
>
>
>

>


|
>

|
|
<
|
<
|
>


|
<
|
>
|
|
|
|
<
|
<
<
<
|
>
<
<
<
<

<
<
|
|
|
<

|
>
|
|
>



|
|
|
>
|
|
|







|








|
>

|
|
>

|
>

|
|


|



|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|

|

<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
|
<
|
<
<
<

<
|
<
|
|
<
<
<
<
<
<

<
<
|
<

<












|
|
|
>
|
|
|





|










|
>

|
|
>

|
|
>

|
|


|










|
>

|
|
>



|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>




|
|
|
>
|
|
|






|
>
>
>



|

|






|
>

|
|
>

|

|
>

|
|
|
>

|
|
>







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
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
	   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.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 (void)
{
#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 :
  # 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 (void)
{
#if BYTE_ORDER != BIG_ENDIAN
		 not big endian
		#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_c_bigendian=yes
else case e in #(
  e) ac_cv_c_bigendian=no ;;
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
    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 (void)
{
#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
	      bogus endian macros
	     #endif

  ;
  return 0;
}
_ACEOF
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 (void)
{
#ifndef _BIG_ENDIAN
		 not big endian
		#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_c_bigendian=yes
else case e in #(
  e) ac_cv_c_bigendian=no ;;
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
    fi
    if test $ac_cv_c_bigendian = unknown; then
      # Compile a test program.
      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.  */
unsigned short int ascii_mm[] =
		  { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
		unsigned short int ascii_ii[] =
		  { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
		int use_ascii (int i) {
		  return ascii_mm[i] + ascii_ii[i];
		}
		unsigned short int ebcdic_ii[] =
		  { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
		unsigned short int ebcdic_mm[] =
		  { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
		int use_ebcdic (int i) {
		  return ebcdic_mm[i] + ebcdic_ii[i];
		}


		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++;

		  ascii_ii[1] = *p++; ebcdic_ii[1] = *p++;
		  return use_ascii (argc) == use_ebcdic (*p);
		}
_ACEOF
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_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.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 (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 :
  ac_cv_c_bigendian=no
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 ;;
esac
fi

    fi ;;
esac
fi
{ 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)
     printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h
;; #(
   no)
      ;; #(
   universal)
     #


     ;; #(
   *)
     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
do :
  ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd"
if test "x$ac_cv_func_getcwd" = xyes

then :
  printf "%s\n" "#define HAVE_GETCWD 1" >>confdefs.h


else case e in #(
  e)
printf "%s\n" "#define USEGETWD 1" >>confdefs.h
 ;;
esac
fi


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 :
  printf "%s\n" "#define HAVE_MKSTEMP 1" >>confdefs.h

else case e in #(
  e) case " $LIBOBJS " in
  *" mkstemp.$ac_objext "* ) ;;
  *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext"
 ;;
esac











 ;;
esac

fi














ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid"
if test "x$ac_cv_func_waitpid" = xyes
then :
  printf "%s\n" "#define HAVE_WAITPID 1" >>confdefs.h

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 :

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 :

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 :

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" "mknod" "ac_cv_func_mknod"
if test "x$ac_cv_func_mknod" = xyes
then :

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 :

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 :

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
do :
  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 :
  cat >>confdefs.h <<_ACEOF
#define `printf "%s\n" "HAVE_$ac_func" | sed "$as_sed_cpp"` 1
_ACEOF

else case e in #(
  e) NEED_FAKE_RFC2553=1 ;;
esac
fi


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 :


printf "%s\n" "#define HAVE_STRUCT_ADDRINFO 1" >>confdefs.h



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 :


printf "%s\n" "#define HAVE_STRUCT_IN6_ADDR 1" >>confdefs.h



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 :


printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_IN6 1" >>confdefs.h



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 :


printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_STORAGE 1" >>confdefs.h



else case e in #(
  e) NEED_FAKE_RFC2553=1 ;;
esac
fi

if test "x$NEED_FAKE_RFC2553" = "x1"; then

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 :

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 :

    { 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 (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 :
  tcl_cv_api_getpwuid_r_5=yes
else case e in #(
  e) tcl_cv_api_getpwuid_r_5=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_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

printf "%s\n" "#define HAVE_GETPWUID_R_5 1" >>confdefs.h

    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 (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 :
  tcl_cv_api_getpwuid_r_4=yes
else case e in #(
  e) tcl_cv_api_getpwuid_r_4=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_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

printf "%s\n" "#define HAVE_GETPWUID_R_4 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

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 :

    { 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 (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 :
  tcl_cv_api_getpwnam_r_5=yes
else case e in #(
  e) tcl_cv_api_getpwnam_r_5=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_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

printf "%s\n" "#define HAVE_GETPWNAM_R_5 1" >>confdefs.h

    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 (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 :
  tcl_cv_api_getpwnam_r_4=yes
else case e in #(
  e) tcl_cv_api_getpwnam_r_4=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_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

printf "%s\n" "#define HAVE_GETPWNAM_R_4 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

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 :

    { 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 (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 :
  tcl_cv_api_getgrgid_r_5=yes
else case e in #(
  e) tcl_cv_api_getgrgid_r_5=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_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

printf "%s\n" "#define HAVE_GETGRGID_R_5 1" >>confdefs.h

    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 (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 :
  tcl_cv_api_getgrgid_r_4=yes
else case e in #(
  e) tcl_cv_api_getgrgid_r_4=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_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

printf "%s\n" "#define HAVE_GETGRGID_R_4 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

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 :

    { 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 (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 :
  tcl_cv_api_getgrnam_r_5=yes
else case e in #(
  e) tcl_cv_api_getgrnam_r_5=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_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

printf "%s\n" "#define HAVE_GETGRNAM_R_5 1" >>confdefs.h

    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 (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 :
  tcl_cv_api_getgrnam_r_4=yes
else case e in #(
  e) tcl_cv_api_getgrnam_r_4=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_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

printf "%s\n" "#define HAVE_GETGRNAM_R_4 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

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.

printf "%s\n" "#define HAVE_MTSAFE_GETHOSTBYNAME 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.

printf "%s\n" "#define HAVE_MTSAFE_GETHOSTBYNAME 1" >>confdefs.h


printf "%s\n" "#define HAVE_MTSAFE_GETHOSTBYADDR 1" >>confdefs.h


else

    # Avoids picking hidden internal symbol from libc
    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 case e in #(
  e) ac_have_decl=0 ;;
esac
fi


printf "%s\n" "#define HAVE_DECL_GETHOSTBYNAME_R $ac_have_decl" >>confdefs.h

if test $ac_have_decl = 1
then :

    tcl_cv_api_gethostbyname_r=yes
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 :

    { 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 (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 :
  tcl_cv_api_gethostbyname_r_6=yes
else case e in #(
  e) tcl_cv_api_gethostbyname_r_6=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_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

printf "%s\n" "#define HAVE_GETHOSTBYNAME_R_6 1" >>confdefs.h

    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 (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 :
  tcl_cv_api_gethostbyname_r_5=yes
else case e in #(
  e) tcl_cv_api_gethostbyname_r_5=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_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

printf "%s\n" "#define HAVE_GETHOSTBYNAME_R_5 1" >>confdefs.h

	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 (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 :
  tcl_cv_api_gethostbyname_r_3=yes
else case e in #(
  e) tcl_cv_api_gethostbyname_r_3=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_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

printf "%s\n" "#define HAVE_GETHOSTBYNAME_R_3 1" >>confdefs.h

	    fi
	fi
    fi
    if test "$tcl_ok" = yes; then

printf "%s\n" "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h

    fi

fi

    fi


    # Avoids picking hidden internal symbol from libc
    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 case e in #(
  e) ac_have_decl=0 ;;
esac
fi


printf "%s\n" "#define HAVE_DECL_GETHOSTBYADDR_R $ac_have_decl" >>confdefs.h

if test $ac_have_decl = 1
then :

    tcl_cv_api_gethostbyaddr_r=yes
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 :

    { 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 (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 :
  tcl_cv_api_gethostbyaddr_r_7=yes
else case e in #(
  e) tcl_cv_api_gethostbyaddr_r_7=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_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

printf "%s\n" "#define HAVE_GETHOSTBYADDR_R_7 1" >>confdefs.h

    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 (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 :
  tcl_cv_api_gethostbyaddr_r_8=yes
else case e in #(
  e) tcl_cv_api_gethostbyaddr_r_8=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_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

printf "%s\n" "#define HAVE_GETHOSTBYADDR_R_8 1" >>confdefs.h

	fi
    fi
    if test "$tcl_ok" = yes; then

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.
#---------------------------------------------------------------------------



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

then :
  printf "%s\n" "#define HAVE_TERMIOS_H 1" >>confdefs.h


fi





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

then :
  printf "%s\n" "#define HAVE_SYS_IOCTL_H 1" >>confdefs.h


fi





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

then :
  printf "%s\n" "#define HAVE_SYS_MODEM_H 1" >>confdefs.h


fi




#--------------------------------------------------------------------
#	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.
#--------------------------------------------------------------------

{ 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 (void)
{
fd_set readMask, writeMask;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_type_fd_set=yes
else case e in #(
  e) tcl_cv_type_fd_set=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_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
    { 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_TRADITIONAL "fd_mask" >/dev/null 2>&1
then :
  tcl_cv_grep_fd_mask=present
else case e in #(
  e) tcl_cv_grep_fd_mask=missing ;;
esac
fi
rm -rf conftest*
 ;;
esac
fi
{ 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

printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h

	tcl_ok=yes
    fi
fi
if test $tcl_ok = no; then

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
#------------------------------------------------------------------------

{ 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)
	{ 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_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


printf "%s\n" "#define NOTIFIER_EPOLL 1" >>confdefs.h

fi

done

	       for ac_header in sys/eventfd.h
do :
  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

then :
  printf "%s\n" "#define HAVE_SYS_EVENTFD_H 1" >>confdefs.h


printf "%s\n" "#define HAVE_EVENTFD 1" >>confdefs.h

fi

done;;

  xDragonFlyBSD|xFreeBSD|xNetBSD|xOpenBSD)
	{ 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
do :
  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 `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 :


printf "%s\n" "#define NOTIFIER_KQUEUE 1" >>confdefs.h

fi;;
  xDarwin)
	# Assume that we've got CoreFoundation present (checked elsewhere because
	# of wider impact).
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: OSX" >&5
printf "%s\n" "OSX" >&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.
#------------------------------------------------------------------------------




    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

then :
  printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h


fi















    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

fi

ac_fn_c_check_func "$LINENO" "mktime" "ac_cv_func_mktime"
if test "x$ac_cv_func_mktime" = xyes
then :
  printf "%s\n" "#define HAVE_MKTIME 1" >>confdefs.h

fi















    { 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 :
  printf %s "(cached) " >&6
else case e in #(
  e)
	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <time.h>
int
main (void)
{
struct tm tm; (void)tm.tm_tzadj;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_member_tm_tzadj=yes
else case e in #(
  e) tcl_cv_member_tm_tzadj=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_member_tm_tzadj" >&5
printf "%s\n" "$tcl_cv_member_tm_tzadj" >&6; }
    if test $tcl_cv_member_tm_tzadj = yes ; then

printf "%s\n" "#define HAVE_TM_TZADJ 1" >>confdefs.h

    fi

    { 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 (void)
{
struct tm tm; (void)tm.tm_gmtoff;
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_member_tm_gmtoff=yes
else case e in #(
  e) tcl_cv_member_tm_gmtoff=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_member_tm_gmtoff" >&5
printf "%s\n" "$tcl_cv_member_tm_gmtoff" >&6; }
    if test $tcl_cv_member_tm_gmtoff = yes ; then

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.
    #
    { 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 (void)
{
extern long timezone;
	    timezone += 1;
	    exit (0);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_timezone_long=yes
else case e in #(
  e) tcl_cv_timezone_long=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_timezone_long" >&5
printf "%s\n" "$tcl_cv_timezone_long" >&6; }
    if test $tcl_cv_timezone_long = yes ; then

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.
	#
	{ 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 (void)
{
extern time_t timezone;
		timezone += 1;
		exit (0);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_timezone_time=yes
else case e in #(
  e) tcl_cv_timezone_time=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_timezone_time" >&5
printf "%s\n" "$tcl_cv_timezone_time" >&6; }
	if test $tcl_cv_timezone_time = yes ; then

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 :


printf "%s\n" "#define HAVE_STRUCT_STAT_ST_BLOCKS 1" >>confdefs.h



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 :


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 :


printf "%s\n" "#define HAVE_BLKCNT_T 1" >>confdefs.h



fi

ac_fn_c_check_func "$LINENO" "fstatfs" "ac_cv_func_fstatfs"
if test "x$ac_cv_func_fstatfs" = xyes
then :

else case e in #(
  e)
printf "%s\n" "#define NO_FSTATFS 1" >>confdefs.h



































































 ;;
esac
fi


#--------------------------------------------------------------------
#       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 case e in #(
  e)

printf "%s\n" "#define NO_MEMMOVE 1" >>confdefs.h


printf "%s\n" "#define NO_STRING_H 1" >>confdefs.h

























































  ;;
esac


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 :

else case e in #(
  e)

printf "%s\n" "#define mode_t int" >>confdefs.h

 ;;
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 :

else case e in #(
  e)                                         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

          #if defined _WIN64 && !defined __CYGWIN__
          LLP64
          #endif

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 :

else case e in #(
  e)

printf "%s\n" "#define size_t unsigned int" >>confdefs.h

 ;;
esac
fi

ac_fn_c_check_type "$LINENO" "uid_t" "ac_cv_type_uid_t" "$ac_includes_default"

if test "x$ac_cv_type_uid_t" = xyes
then :

else case e in #(
  e)
printf "%s\n" "#define uid_t int" >>confdefs.h

 ;;



esac
fi







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 :


else case e in #(
  e)
printf "%s\n" "#define gid_t int" >>confdefs.h
 ;;
esac
fi


{ 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 (void)
{

    	socklen_t foo;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_type_socklen_t=yes
else case e in #(
  e) tcl_cv_type_socklen_t=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_type_socklen_t" >&5
printf "%s\n" "$tcl_cv_type_socklen_t" >&6; }
if test $tcl_cv_type_socklen_t = no; then

printf "%s\n" "#define socklen_t int" >>confdefs.h

fi

ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "

















#include <stdint.h>






"


























if test "x$ac_cv_type_intptr_t" = xyes
then :

printf "%s\n" "#define HAVE_INTPTR_T 1" >>confdefs.h






























fi





ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "

#include <stdint.h>





"

if test "x$ac_cv_type_uintptr_t" = xyes
then :









printf "%s\n" "#define HAVE_UINTPTR_T 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.
#--------------------------------------------------------------------

{ 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 (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 :
  tcl_cv_union_wait=yes
else case e in #(
  e) tcl_cv_union_wait=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext ;;
esac
fi
{ 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

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 :
  tcl_ok=1
else case e in #(
  e) tcl_ok=0 ;;
esac
fi

if test "$tcl_ok" = 0; then
    { 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.
   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 (void);
int
main (void)
{
return strncasecmp ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_socket_strncasecmp=yes
else case e in #(
  e) ac_cv_lib_socket_strncasecmp=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 case e in #(
  e) tcl_ok=0 ;;
esac
fi

fi
if test "$tcl_ok" = 0; then
    { 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.
   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 (void);
int
main (void)
{
return strncasecmp ();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_lib_inet_strncasecmp=yes
else case e in #(
  e) ac_cv_lib_inet_strncasecmp=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ 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 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
#	   (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 :


else


$as_echo "#define NO_GETTOD 1" >>confdefs.h



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

    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 :

  tcl_cv_grep_gettimeofday=present
else
  tcl_cv_grep_gettimeofday=missing

fi
rm -f conftest*


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_grep_gettimeofday" >&5
$as_echo "$tcl_cv_grep_gettimeofday" >&6; }
if test $tcl_cv_grep_gettimeofday = missing ; then

$as_echo "#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
/* end confdefs.h.  */
$ac_includes_default
int
main ()
{
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 :

  ac_cv_c_char_unsigned=no
else
  ac_cv_c_char_unsigned=yes

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

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

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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

	signed char *p;
	p = 0;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_char_signed=yes
else
  tcl_cv_char_signed=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_char_signed" >&5
$as_echo "$tcl_cv_char_signed" >&6; }
if test $tcl_cv_char_signed = yes; then

$as_echo "#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 :

  tcl_cv_putenv_copy=no
else
  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[])
	{







|
>

|
|

|

|
>


|
|
|
>
|
|
|






|
>

|
|
>

|
|
>

|
|


|









|
|
|
>
|
|
|



|









|
>

|
|
>

|
>

|
|
|
|



|
|
|
>
|
|
|




|









|
>

|
|
>

|
>

|
|


|







|
|
|
>
|
|
|
|
>

|
|







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
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
#	   (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 :

else case e in #(
  e)

printf "%s\n" "#define NO_GETTOD 1" >>confdefs.h

 ;;
esac
fi

{ 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_TRADITIONAL "gettimeofday" >/dev/null 2>&1
then :
  tcl_cv_grep_gettimeofday=present
else case e in #(
  e) tcl_cv_grep_gettimeofday=missing ;;
esac
fi
rm -rf conftest*
 ;;
esac
fi
{ 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

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.
#--------------------------------------------------------------------

{ 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 (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 :
  ac_cv_c_char_unsigned=no
else case e in #(
  e) ac_cv_c_char_unsigned=yes ;;
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_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

{ 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 (void)
{

	signed char *p;
	p = 0;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_char_signed=yes
else case e in #(
  e) tcl_cv_char_signed=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_char_signed" >&5
printf "%s\n" "$tcl_cv_char_signed" >&6; }
if test $tcl_cv_char_signed = yes; then

printf "%s\n" "#define HAVE_SIGNED_CHAR 1" >>confdefs.h

fi

#--------------------------------------------------------------------
#  Does putenv() copy or not?  We need to know to avoid memory leaks.
#--------------------------------------------------------------------

{ 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 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
	    } else {
		/* does copy */
		return 1;
	    }
	}

_ACEOF
if ac_fn_c_try_run "$LINENO"; then :

  tcl_cv_putenv_copy=no
else
  tcl_cv_putenv_copy=yes

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_putenv_copy" >&5
$as_echo "$tcl_cv_putenv_copy" >&6; }
if test $tcl_cv_putenv_copy = yes; then

$as_echo "#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 :

  enableval=$enable_langinfo; langinfo_ok=$enableval
else
  langinfo_ok=yes

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 :

  langinfo_ok=yes
else
  langinfo_ok=no

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; }
    if test "$langinfo_ok" = "yes"; then
	if ${tcl_cv_langinfo_h+:} false; then :

  $as_echo_n "(cached) " >&6
else

	    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */
#include <langinfo.h>
int
main ()
{
nl_langinfo(CODESET);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_langinfo_h=yes
else
  tcl_cv_langinfo_h=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi

	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_langinfo_h" >&5
$as_echo "$tcl_cv_langinfo_h" >&6; }
	if test $tcl_cv_langinfo_h = yes; then

$as_echo "#define HAVE_LANGINFO 1" >>confdefs.h

	fi
    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $langinfo_ok" >&5
$as_echo "$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
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF

fi
done


#--------------------------------------------------------------------
# Check for support of isnan() function or macro
#--------------------------------------------------------------------

{ $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

    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
$as_echo "$tcl_cv_isnan" >&6; }
if test $tcl_cv_isnan = no; then

$as_echo "#define NO_ISNAN 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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_GETATTRLIST 1
_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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_COPYFILE_H 1
_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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_COPYFILE 1
_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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_LIBKERN_OSATOMIC_H 1
_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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_OSSPINLOCKLOCK 1
_ACEOF

fi
done

    fi

$as_echo "#define USE_VFORK 1" >>confdefs.h


$as_echo "#define TCL_LOAD_FROM_MEMORY 1" >>confdefs.h


$as_echo "#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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_AVAILABILITYMACROS_H 1
_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

	    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 ()
{
rand();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_cc_weak_import=yes
else
  tcl_cv_cc_weak_import=no

fi
rm -f core conftest.err conftest.$ac_objext \
    conftest$ac_exeext conftest.$ac_ext
	    CFLAGS=$hold_cflags

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_weak_import" >&5
$as_echo "$tcl_cv_cc_weak_import" >&6; }
	if test $tcl_cv_cc_weak_import = yes; then

$as_echo "#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

	    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 ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_cc_darwin_c_source=yes
else
  tcl_cv_cc_darwin_c_source=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
	    CFLAGS=$hold_cflags

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; }
	if test $tcl_cv_cc_darwin_c_source = yes; then

$as_echo "#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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

	    #include <sys/param.h>
	    #include <sys/stat.h>
	    #include <fts.h>

int
main ()
{

	    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 :

  tcl_cv_api_fts=yes
else
  tcl_cv_api_fts=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_api_fts" >&5
$as_echo "$tcl_cv_api_fts" >&6; }
if test $tcl_cv_api_fts = yes; then

$as_echo "#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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_SYS_IOCTL_H 1
_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 :
  cat >>confdefs.h <<_ACEOF

#define HAVE_SYS_FILIO_H 1
_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

	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;}
		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


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5
$as_echo "$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; }
    case $system in
	OSF*)

$as_echo "#define USE_FIONBIO 1" >>confdefs.h

	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: FIONBIO" >&5
$as_echo "FIONBIO" >&6; }
	    ;;
	*)
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: O_NONBLOCK" >&5
$as_echo "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; }
# Check whether --enable-dll-unloading was given.
if test "${enable_dll_unloading+set}" = set; then :

  enableval=$enable_dll_unloading; tcl_ok=$enableval
else
  tcl_ok=yes

fi

if test $tcl_ok = yes; then

$as_echo "#define TCL_UNLOAD_DLLS 1" >>confdefs.h

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5
$as_echo "$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; }

# Check whether --with-tzdata was given.
if test "${with_tzdata+set}" = set; then :

  withval=$with_tzdata; tcl_ok=$withval
else
  tcl_ok=auto

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; }
    ;;
    yes)
	# nothing to do here
    ;;
    auto*)
	if ${tcl_cv_dir_zoneinfo+:} false; then :

  $as_echo_n "(cached) " >&6
else

	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

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; }
	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; }
    INSTALL_TZDATA=install-tzdata
fi

#--------------------------------------------------------------------
#	DTrace support
#--------------------------------------------------------------------

# Check whether --enable-dtrace was given.
if test "${enable_dtrace+set}" = set; then :

  enableval=$enable_dtrace; tcl_ok=$enableval
else
  tcl_ok=no

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 :

  tcl_ok=yes
else
  tcl_ok=no

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
  [\\/]* | ?:[\\/]*)
  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

  test -z "$as_dir" && as_dir=.



    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
    break 2
  fi
done
  done
IFS=$as_save_IFS

  ;;

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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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; }
MAKEFILE_SHELL='/bin/sh'
if test $tcl_ok = yes; then

$as_echo "#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; }

#--------------------------------------------------------------------
#	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

    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

	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");

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_cpuid=yes
else
  tcl_cv_cpuid=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_cpuid" >&5
$as_echo "$tcl_cv_cpuid" >&6; }
if test $tcl_cv_cpuid = yes; then

$as_echo "#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.
#--------------------------------------------------------------------







|
>

|
|
>


|
>

|
>

|
|


|









|
>

|
|
>





|
|
>

|
|
>


<

|
|

|
>
|
|
|




|






|
>

|
|
>

|
>


|
|


|



|
|







<
<
<
|
>
|
|
<
<


<
|
|
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<

<
<
<
|
<
|
|
|


>






<
<
|
|
<
>
|
<


<

<
<
|
|
<
>
|
<



<
<
<
<
|
|
<
>
|
<


<


<
<
|
|
<
>
|
<



<
<
<
<
|
|
<
>
|
<


<



<
<
<
|


|

<
<
|
|
<
>
|
<


<
<


|
|
|
>
|
|
|














|






|
>

|
|
>

|

|
>

|
|


|


|
|
|
>
|
|
|















|






|
>

|
|
>

|
|
>

|
|


|















|
|
|
>
|
|
|








|










|
>

|
|
>

|
|
>

|
|


|










<
<
|
|
<
>
|
<



<
<
<
<
|
|
<
>
|
<



<

<
|
|
|
>
|
|
|





|
|










|
>

|
|


|
|



|

|
|


|
|






|
|

|
>

|
|
>




|


|
|







|
|


|
>

|
|
>








|
|





|
>
|
|
|









|
>




|
|










|
|








|
>

|
|
>



|
|
>

|
|
>

<





|
|
|
>
|
|
|









>
|
>
>
>

|
|
|







>




|
|

|
|





|
|



|

















|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





|
|
|
>
|
|
|




|














|
>

|
|
>

|
|
>

|
|


|







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
10978
10979
10980
10981
10982
10983
10984
10985
10986
10987
10988
10989
10990
10991
10992
10993
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
	    } else {
		/* does copy */
		return 1;
	    }
	}

_ACEOF
if ac_fn_c_try_run "$LINENO"
then :
  tcl_cv_putenv_copy=no
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 ;;
esac
fi
 ;;
esac
fi
{ 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

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+y}
then :
  enableval=$enable_langinfo; langinfo_ok=$enableval
else case e in #(
  e) langinfo_ok=yes ;;
esac
fi


    HAVE_LANGINFO=0
    if test "$langinfo_ok" = "yes"; 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 case e in #(
  e) langinfo_ok=no ;;
esac
fi


    fi
    { 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 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 (void)
{
nl_langinfo(CODESET);
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_langinfo_h=yes
else case e in #(
  e) tcl_cv_langinfo_h=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_langinfo_h" >&5
printf "%s\n" "$tcl_cv_langinfo_h" >&6; }
	if test $tcl_cv_langinfo_h = yes; then

printf "%s\n" "#define HAVE_LANGINFO 1" >>confdefs.h

	fi
    else
	{ 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
#--------------------------------------------------------------------




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



fi

ac_fn_c_check_func "$LINENO" "chflags" "ac_cv_func_chflags"
if test "x$ac_cv_func_chflags" = xyes



then :





  printf "%s\n" "#define HAVE_CHFLAGS 1" >>confdefs.h

















fi



ac_fn_c_check_func "$LINENO" "mkstemps" "ac_cv_func_mkstemps"

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


    ac_fn_c_check_func "$LINENO" "getattrlist" "ac_cv_func_getattrlist"
if test "x$ac_cv_func_getattrlist" = xyes

then :
  printf "%s\n" "#define HAVE_GETATTRLIST 1" >>confdefs.h


fi




    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

then :
  printf "%s\n" "#define HAVE_COPYFILE_H 1" >>confdefs.h


fi





    ac_fn_c_check_func "$LINENO" "copyfile" "ac_cv_func_copyfile"
if test "x$ac_cv_func_copyfile" = xyes

then :
  printf "%s\n" "#define HAVE_COPYFILE 1" >>confdefs.h


fi


    if test $tcl_corefoundation = yes; 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

then :
  printf "%s\n" "#define HAVE_LIBKERN_OSATOMIC_H 1" >>confdefs.h


fi





	ac_fn_c_check_func "$LINENO" "OSSpinLockLock" "ac_cv_func_OSSpinLockLock"
if test "x$ac_cv_func_OSSpinLockLock" = xyes

then :
  printf "%s\n" "#define HAVE_OSSPINLOCKLOCK 1" >>confdefs.h


fi


    fi




printf "%s\n" "#define TCL_LOAD_FROM_MEMORY 1" >>confdefs.h


printf "%s\n" "#define TCL_WIDE_CLICKS 1" >>confdefs.h



    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

then :
  printf "%s\n" "#define HAVE_AVAILABILITYMACROS_H 1" >>confdefs.h


fi



    if test "$ac_cv_header_AvailabilityMacros_h" = yes; then
	{ 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 (void)
{
rand();
  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cc_weak_import=yes
else case e in #(
  e) tcl_cv_cc_weak_import=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_weak_import" >&5
printf "%s\n" "$tcl_cv_cc_weak_import" >&6; }
	if test $tcl_cv_cc_weak_import = yes; then

printf "%s\n" "#define HAVE_WEAK_IMPORT 1" >>confdefs.h

	fi
	{ 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_cc_darwin_c_source=yes
else case e in #(
  e) tcl_cv_cc_darwin_c_source=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_darwin_c_source" >&5
printf "%s\n" "$tcl_cv_cc_darwin_c_source" >&6; }
	if test $tcl_cv_cc_darwin_c_source = yes; then

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)
#--------------------------------------------------------------------

{ 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 (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 :
  tcl_cv_api_fts=yes
else case e in #(
  e) tcl_cv_api_fts=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext ;;
esac
fi
{ 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

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.
#--------------------------------------------------------------------




    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

then :
  printf "%s\n" "#define HAVE_SYS_IOCTL_H 1" >>confdefs.h


fi





    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

then :
  printf "%s\n" "#define HAVE_SYS_FILIO_H 1" >>confdefs.h


fi




    { 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
		{ 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
{ 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

    { 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*)

printf "%s\n" "#define USE_FIONBIO 1" >>confdefs.h

	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: FIONBIO" >&5
printf "%s\n" "FIONBIO" >&6; }
	    ;;
	*)
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: O_NONBLOCK" >&5
printf "%s\n" "O_NONBLOCK" >&6; }
	    ;;
    esac


#------------------------------------------------------------------------

{ 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+y}
then :
  enableval=$enable_dll_unloading; tcl_ok=$enableval
else case e in #(
  e) tcl_ok=yes ;;
esac
fi

if test $tcl_ok = yes; then

printf "%s\n" "#define TCL_UNLOAD_DLLS 1" >>confdefs.h

fi
{ 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.
#------------------------------------------------------------------------

{ 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+y}
then :
  withval=$with_tzdata; tcl_ok=$withval
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)
	{ 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 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 ;;
esac
fi

	if test -n "$tcl_cv_dir_zoneinfo"; then
	    tcl_ok=no
	    { 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
    { 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+y}
then :
  enableval=$enable_dtrace; tcl_ok=$enableval
else case e in #(
  e) tcl_ok=no ;;
esac
fi

if test $tcl_ok = yes; 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 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
{ 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 #(((
    '') 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"
    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
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5
printf "%s\n" "$DTRACE" >&6; }
else
  { 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
{ 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

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
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_ok" >&5
printf "%s\n" "$tcl_ok" >&6; }






































































































































































#--------------------------------------------------------------------
# The check below checks whether the cpuid instruction is usable.
#--------------------------------------------------------------------

{ 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 (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");

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_cpuid=yes
else case e in #(
  e) tcl_cv_cpuid=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext ;;
esac
fi
{ 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

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
# 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; }
	# Check whether --enable-framework was given.
if test "${enable_framework+set}" = set; then :

  enableval=$enable_framework; enable_framework=$enableval
else
  enable_framework=no

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;}
		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;}
		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; }
	    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; }
	    else
		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: static library" >&5
$as_echo "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

    # 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







|
|

|
>

|
|
>




|
|



|
|




|
|



|
|

|
|










<







|







11071
11072
11073
11074
11075
11076
11077
11078
11079
11080
11081
11082
11083
11084
11085
11086
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
# 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
	{ 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+y}
then :
  enableval=$enable_framework; enable_framework=$enableval
else case e in #(
  e) enable_framework=no ;;
esac
fi

	if test $enable_framework = yes; then
	    if test $SHARED_BUILD = 0; then
		{ 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
		{ 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
	    { 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
		{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared library" >&5
printf "%s\n" "shared library" >&6; }
	    else
		{ 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'

    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

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
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
    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}
















































































































































































































#--------------------------------------------------------------------
#	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"
    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}"
else
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="{${prefix}/lib} ${TCL_PACKAGE_PATH}"
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=\"${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 .`"
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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|



|

|










|



<
<
<
|
<







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
11353
11354
11355
11356
11357
11358
11359
11360
11361
11362
11363
11364
11365
11366
11367
11368
11369
11370
11371
11372
11373
11374
11375
11376
11377
11378
11379
11380
11381
11382
11383
11384
11385
11386
11387
11388
11389
11390
11391
11392
11393
11394
11395
11396
11397
11398
11399
11400
11401
11402
11403
11404
11405
11406
11407
11408
11409
11410
11411
11412
11413
11414
11415
11416
11417
11418
11419



11420

11421
11422
11423
11424
11425
11426
11427
    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"
    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"
else
    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.a"
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_DIR=\"${libdir}\""




TCL_STUB_LIB_FLAG="-ltclstub"


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
# 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}'







|
|















|
|












|






|









|






|
|













|
|







11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514
11515
11516
11517
11518
11519
11520
11521
11522
11523
11524
11525
11526
11527
11528
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
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
# 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_*) { 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
      # 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+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
      { 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
    { 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
: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`



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;}
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.







|
<
<
















<




|
|







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
:clear
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
t quote
s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
t quote
b any
:quote
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"
{ 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
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.







|
>






|
|




>




>
>
>
>
>
>
>
>



<
<
<
<
<
<
<
<
|
|
<
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
>
>
|
<
<
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>


|








<
<
<
<
<
<
<








>
|
>
>
>
|





|





|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












|

|







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
11699
11700
11701
11702
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
11744
11745
11746
11747
11748
11749
11750
11751




















11752
11753
11754
11755
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769
11770
11771
11772
11773
cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##

# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
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 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








IFS=" ""	$as_nl"


PS1='$ '
PS2='> '






PS4='+ '








# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL


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 ${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









# 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 #(((
    '') 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'
# 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
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi























# 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
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  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
# ---------------
# 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







>






|
>




|
|


|
>







|
>




|
|


|
>







11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
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
# ---------------
# 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 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 :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
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
  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







|







11854
11855
11856
11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
  as_dirname=false
fi

as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
	 X"$0" : 'X\(//\)$' \| \
	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
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
# 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







>
>
>
>












>
>
>
>
>
>












|
|
|







11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899
11900
11901
11902
11903
11904
11905
11906
11907
11908
11909
11910
11911
11912
11913
11914
11915
11916
11917
11918
11919
11920
11921
11922
11923
11924
11925
11926
# 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'.
    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
  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







|








|







11940
11941
11942
11943
11944
11945
11946
11947
11948
11949
11950
11951
11952
11953
11954
11955
11956
11957
11958
11959
11960
11961
11962
11963
  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=`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 ||
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
{
  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 tcl $as_me 9.0, 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 $@








|
>


|
>















|







11993
11994
11995
11996
11997
11998
11999
12000
12001
12002
12003
12004
12005
12006
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026
12027
12028
{
  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_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_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.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
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
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







|







12042
12043
12044
12045
12046
12047
12048
12049
12050
12051
12052
12053
12054
12055
12056
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
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

Configuration commands:
$config_commands

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="\\
tcl config.status 9.0
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







>
>

|


|


|







12067
12068
12069
12070
12071
12072
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090

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='$ac_cs_config_escaped'
ac_cs_version="\\
tcl config.status 9.0
configured by $0, generated by GNU Autoconf 2.72,
  with options \\"\$ac_cs_config\\"

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
  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
#
# INIT-COMMANDS
#







|

|





|





|





|
|




















|













|







12113
12114
12115
12116
12117
12118
12119
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
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
  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 )
    printf "%s\n" "$ac_cs_version"; exit ;;
  --config | --confi | --conf | --con | --co | --c )
    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=`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 )
    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_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
  \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
  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
    "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;;
  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
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







|









|
|







|







12195
12196
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206
12207
12208
12209
12210
12211
12212
12213
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
    "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;;
  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+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'.
$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
  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.







|







12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
  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.
11516
11517
11518
11519
11520
11521
11522
11523
11524
11525
11526
11527
11528
11529
11530
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







|







12404
12405
12406
12407
12408
12409
12410
12411
12412
12413
12414
12415
12416
12417
12418
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
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
    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







|





|

|



|



|



|
|




|
















|







12426
12427
12428
12429
12430
12431
12432
12433
12434
12435
12436
12437
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469
12470
12471
12472
12473
12474
12475
12476
12477
12478
12479
12480
12481
12482
12483
    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=`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
    # use $as_me), people would be surprised to read:
    #    /* config.h.  Generated by config.status.  */
    configure_input='Generated from '`
	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	`' by configure.'
    if test x"$ac_file" != x-; then
      configure_input="$ac_file.  $configure_input"
      { 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=`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 ||
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
	  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







|

|







12493
12494
12495
12496
12497
12498
12499
12500
12501
12502
12503
12504
12505
12506
12507
12508
12509
	  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=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  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
/@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







|
|












|







12548
12549
12550
12551
12552
12553
12554
12555
12556
12557
12558
12559
12560
12561
12562
12563
12564
12565
12566
12567
12568
12569
12570
12571
12572
12573
12574
12575
12576
/@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@*)
  { 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' = '.'.
# 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
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
 ;;


  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
$as_echo "$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 &&







|

|











|
|







12591
12592
12593
12594
12595
12596
12597
12598
12599
12600
12601
12602
12603
12604
12605
12606
12607
12608
12609
12610
12611
12612
12613
12614
12615
12616
12617
12618
12619
12620
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"; } &&
  { 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
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)  { 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 &&
11765
11766
11767
11768
11769
11770
11771
11772
11773
11774
11775
11776

  $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










|
|



>
12653
12654
12655
12656
12657
12658
12659
12660
12661
12662
12663
12664
12665
  $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
  { 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
#! /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)

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

    #endif /* _TCLCONFIG */])
])

TCL_VERSION=9.0
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=0
TCL_PATCH_LEVEL="a2"
VERSION=${TCL_VERSION}

EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}

#------------------------------------------------------------------------
# Setup configure arguments for bundled packages






|












|
|
>






|







1
2
3
4
5
6
7
8
9
10
11
12
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])

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_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="b2"
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
# 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)
	CFLAGS=$hold_cflags])
    if test $tcl_cv_cc_pipe = yes; then
	CFLAGS="$CFLAGS -pipe"
    fi
fi

#------------------------------------------------------------------------







|







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_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

#------------------------------------------------------------------------
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186


187
188
189
190
191
192
193
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],
	[use external libtommath (default: true if available, false otherwise)]),
	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_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}])
])








|

|









>
>







169
170
171
172
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_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?])

#------------------------------------------------------------------------
#	Add stuff for libtommath

libtommath_ok=yes
AC_ARG_WITH(system-libtommath,
AS_HELP_STRING([--with-system-libtommath],
	[use external libtommath (default: true if available, false otherwise)]),
	[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
SC_TCL_64BIT_FLAGS

#--------------------------------------------------------------------
#	Check endianness because we can optimize comparisons of
#	Tcl_UniChar strings to memcmp on big-endian systems.
#--------------------------------------------------------------------

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_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(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







|











|



>
>
>







215
216
217
218
219
220
221
222
223
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(,,,[#])

#--------------------------------------------------------------------
#	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 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
#	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)])
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








#------------------------------------------------------------------------
#	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])







|
|













>
>
>
>
>
>
>







303
304
305
306
307
308
309
310
311
312
313
314
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_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
#--------------------------------------------------------------------
#	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])
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([
	#include <sys/types.h>
	#include <sys/socket.h>
    ],[
    	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_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
])

#--------------------------------------------------------------------
#	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>], [
union wait x;
WIFEXITED(x);		/* Generates compiler error if WIFEXITED
			 * uses an int. */
    ], 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







|




<
<
<
<
<
<
<










<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<











|


|

|




|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<










|
|



|







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
#--------------------------------------------------------------------
#	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, 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 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>?]) ])





















#--------------------------------------------------------------------
#	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_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])])
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_TYPES([intptr_t, uintptr_t],,,[[






























#include <stdint.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_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])])
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
#	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(, [
	signed char *p;
	p = 0;
	], 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([
	#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)])
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([
		    #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)
	    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([
		    #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)
	    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([
	    #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)])
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],
	[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],
	[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







|


|









|


















|
|
|
|

















<
<
<
<
<
<
<
<
<
<
<
<












<








|








|
|







|









|



















|



|



|
















|















|







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
#	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_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
	signed char *p;
	p = 0;
	]])],[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_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])])
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)













#--------------------------------------------------------------------
# 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(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_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])
	    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_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])
	    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_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])])
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,
    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,
    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
fi

#--------------------------------------------------------------------
#	DTrace support
#--------------------------------------------------------------------

AC_ARG_ENABLE(dtrace,
    AC_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])







|







683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
fi

#--------------------------------------------------------------------
#	DTrace support
#--------------------------------------------------------------------

AC_ARG_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
	    # 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(, [
	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)])
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.









<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|







|







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
	    # 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])

#--------------------------------------------------------------------














































# The check below checks whether the cpuid instruction is usable.
#--------------------------------------------------------------------

AC_CACHE_CHECK([whether the cpuid instruction is usable], tcl_cv_cpuid, [
    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])])
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
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







<







764
765
766
767
768
769
770

771
772
773
774
775
776
777
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'

    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
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
    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}


















































#--------------------------------------------------------------------
#	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"
    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}"
else
    test -z "$TCL_PACKAGE_PATH" && TCL_PACKAGE_PATH="{${prefix}/lib} ${TCL_PACKAGE_PATH}"
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=\"${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 .`"
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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|



|

|










|



<
<
<
|
<







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
    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"
    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"
else
    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.a"
eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
eval "TCL_STUB_LIB_DIR=\"${libdir}\""




TCL_STUB_LIB_FLAG="-ltclstub"


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
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
LDFLAGS_DEBUG		= @LDFLAGS_DEBUG@
LDFLAGS_OPTIMIZE	= @LDFLAGS_OPTIMIZE@
LDFLAGS			= @LDFLAGS_DEFAULT@ @LDFLAGS@

CC_SWITCHES = $(CFLAGS) -I${SRC_DIR}/../../generic -DTCL_MEM_DEBUG \
	${SHLIB_CFLAGS} -DUSE_TCL_STUBS ${AC_FLAGS}



all: pkga${SHLIB_SUFFIX} pkgb${SHLIB_SUFFIX} pkgc${SHLIB_SUFFIX} pkgd${SHLIB_SUFFIX} pkge${SHLIB_SUFFIX} pkgua${SHLIB_SUFFIX} pkgooa${SHLIB_SUFFIX}
	@if test -n "$(DLTEST_SUFFIX)"; then $(MAKE) dltest_suffix; fi
	@touch ../dltest.marker



dltest_suffix: pkga${DLTEST_SUFFIX} pkgb${DLTEST_SUFFIX} pkgc${DLTEST_SUFFIX} pkgd${DLTEST_SUFFIX} pkge${DLTEST_SUFFIX} pkgua${DLTEST_SUFFIX} pkgooa${DLTEST_SUFFIX}
	@touch ../dltest.marker







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
















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







pkga${SHLIB_SUFFIX}: pkga.o
	${SHLIB_LD} -o pkga${SHLIB_SUFFIX} pkga.o ${SHLIB_LD_LIBS}

pkgb${SHLIB_SUFFIX}: pkgb.o
	${SHLIB_LD} -o pkgb${SHLIB_SUFFIX} pkgb.o ${SHLIB_LD_LIBS}

pkgc${SHLIB_SUFFIX}: pkgc.o
	${SHLIB_LD} -o pkgc${SHLIB_SUFFIX} pkgc.o ${SHLIB_LD_LIBS}
















pkgd${SHLIB_SUFFIX}: pkgd.o
	${SHLIB_LD} -o pkgd${SHLIB_SUFFIX} pkgd.o ${SHLIB_LD_LIBS}

pkge${SHLIB_SUFFIX}: pkge.o
	${SHLIB_LD} -o pkge${SHLIB_SUFFIX} pkge.o ${SHLIB_LD_LIBS}

pkgua${SHLIB_SUFFIX}: pkgua.o
	${SHLIB_LD} -o pkgua${SHLIB_SUFFIX} pkgua.o ${SHLIB_LD_LIBS}

pkgooa${SHLIB_SUFFIX}: pkgooa.o
	${SHLIB_LD} -o pkgooa${SHLIB_SUFFIX} pkgooa.o ${SHLIB_LD_LIBS}




pkga${DLTEST_SUFFIX}: pkga.o
	${DLTEST_LD} -o pkga${DLTEST_SUFFIX} pkga.o ${SHLIB_LD_LIBS}

pkgb${DLTEST_SUFFIX}: pkgb.o
	${DLTEST_LD} -o pkgb${DLTEST_SUFFIX} pkgb.o ${SHLIB_LD_LIBS}

pkgc${DLTEST_SUFFIX}: pkgc.o
	${DLTEST_LD} -o pkgc${DLTEST_SUFFIX} pkgc.o ${SHLIB_LD_LIBS}
















pkgd${DLTEST_SUFFIX}: pkgd.o
	${DLTEST_LD} -o pkgd${DLTEST_SUFFIX} pkgd.o ${SHLIB_LD_LIBS}

pkge${DLTEST_SUFFIX}: pkge.o
	${DLTEST_LD} -o pkge${DLTEST_SUFFIX} pkge.o ${SHLIB_LD_LIBS}

pkgua${DLTEST_SUFFIX}: pkgua.o
	${DLTEST_LD} -o pkgua${DLTEST_SUFFIX} pkgua.o ${SHLIB_LD_LIBS}

pkgooa${DLTEST_SUFFIX}: pkgooa.o
	${DLTEST_LD} -o pkgooa${DLTEST_SUFFIX} pkgooa.o ${SHLIB_LD_LIBS}

clean:
	rm -f *.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} ; \







|




|


>
>
|



>
>
|


>
>
>
>
>
>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












>
>
>
>
>
>
|
|

|
|

|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|

|
|

|
|

|
|

>
>
>
|
|

|
|

|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|

|
|

|
|

|
|


|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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 -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 \
	${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} \
	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} \
	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}

tcl9pkga${SHLIB_SUFFIX}: pkga.o
	${SHLIB_LD} -o $@ pkga.o ${SHLIB_LD_LIBS}

tcl9pkgb${SHLIB_SUFFIX}: pkgb.o
	${SHLIB_LD} -o $@ pkgb.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}

tcl9pkgd${SHLIB_SUFFIX}: pkgd.o
	${SHLIB_LD} -o $@ pkgd.o ${SHLIB_LD_LIBS}

tcl9pkge${SHLIB_SUFFIX}: pkge.o
	${SHLIB_LD} -o $@ pkge.o ${SHLIB_LD_LIBS}

tcl9pkgua${SHLIB_SUFFIX}: pkgua.o
	${SHLIB_LD} -o $@ pkgua.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}

tcl9pkga${DLTEST_SUFFIX}: pkga.o
	${DLTEST_LD} -o $@ pkga.o ${SHLIB_LD_LIBS}

tcl9pkgb${DLTEST_SUFFIX}: pkgb.o
	${DLTEST_LD} -o $@ pkgb.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}

tcl9pkgd${DLTEST_SUFFIX}: pkgd.o
	${DLTEST_LD} -o $@ pkgd.o ${SHLIB_LD_LIBS}

tcl9pkge${DLTEST_SUFFIX}: pkge.o
	${DLTEST_LD} -o $@ pkge.o ${SHLIB_LD_LIBS}

tcl9pkgua${DLTEST_SUFFIX}: pkgua.o
	${DLTEST_LD} -o $@ pkgua.o ${SHLIB_LD_LIBS}

tcl9pkgooa${DLTEST_SUFFIX}: pkgooa.o
	${DLTEST_LD} -o $@ pkgooa.o ${SHLIB_LD_LIBS}

clean:
	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
/*
 * 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.
 *
 * 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. */
    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;
    (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);


    if (len1 == len2) {
	result = (Tcl_UtfNcmp(str1, str2, len1) == 0);
    } else {
	result = 0;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
    return TCL_OK;
}







|








<
<
<
<
<
<
<
<
<




















|






|









>
>

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15









16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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 © 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
Pkga_EqObjCmd(
    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;
    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_NewIntObj(result));
    return TCL_OK;
}

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkga_QuoteObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    (void)dummy;

    if (objc != 2) {







|







76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkga_QuoteObjCmd(
    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
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    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;
}







|








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");
    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
/*
 * 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.
 *
 * 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    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. */
    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);
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(first - second));
    return TCL_OK;
}

/*







|







|
<
|
<
|
<
<
<
<
<
<
|

















<
<
<
<


|














|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

17

18






19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36




37
38
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 © 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)

#   define snprintf _snprintf

#endif







/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */





static int
Pkgb_SubObjCmd(
    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];
	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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgb_UnsafeObjCmd(
    ClientData 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);
}

static int
Pkgb_DemoObjCmd(
    ClientData 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;

    (void)dummy;
    (void)objc;
    (void)objv;



    if (Tcl_ListObjIndex(NULL, Tcl_GetEncodingSearchPath(), 0, &first)
	    == TCL_OK) {
	Tcl_SetObjResult(interp, first);
    }
#else

    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetDefaultEncodingDir(), -1));
#endif
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgb_Init --







|








|




|




<
|
>

|
|
>
>
|
|
|
<

<
>
|
<







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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(
    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", TCL_INDEX_NONE, TCL_EVAL_GLOBAL);
}

static int
Pkgb_DemoObjCmd(
    void *dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{

    Tcl_WideInt numChars;
    int result;
    (void)dummy;

    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;

    }

    result = Tcl_UtfNcmp(Tcl_GetString(objv[1]), Tcl_GetString(objv[2]), (size_t)numChars);
    Tcl_SetObjResult(interp, Tcl_NewIntObj(result));

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgb_Init --
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    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;







|







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");
    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
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    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;
}







|






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");
    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
/*
 * 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.
 *
 * 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. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int first, second;
    (void)dummy;








|








<
<
<
<
<
<
<
<
<



















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16









17
18
19
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 © 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"










/*
 *----------------------------------------------------------------------
 *
 * 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(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgc_UnsafeObjCmd(
    ClientData 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));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgc_Init --







|








|







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(
    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", TCL_INDEX_NONE));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgc_Init --
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    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;







|







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");
    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
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    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;
}







|






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");
    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
/*
 * 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.
 *
 * 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. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int first, second;
    (void)dummy;








|








<
<
<
<
<
<
<
<
<



















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16









17
18
19
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 © 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"










/*
 *----------------------------------------------------------------------
 *
 * 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(
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgd_UnsafeObjCmd(
    ClientData 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));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgd_Init --







|








|







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(
    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", TCL_INDEX_NONE));
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgd_Init --
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    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;







|







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");
    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
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    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;
}







|






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");
    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
/*
 * 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.
 *
 * 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"







|







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 © 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
				 * 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);
}







|

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, TCL_INDEX_NONE, 0);
}

Changes to unix/dltest/pkgooa.c.

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.
 *
 * 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"






|







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 © 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgooa_StubsOKObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    (void)dummy;

    if (objc != 1) {







|







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
Pkgooa_StubsOKObjCmd(
    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
	    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,

};

extern 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? ");
	return TCL_ERROR;
    }
    if (Tcl_OOInitStubs(interp) == NULL) {
	return TCL_ERROR;
    }
    if (tclOOStubsPtr == NULL) {
	Tcl_AppendResult(interp, "TclOO stubs are not inialized");
	return TCL_ERROR;
    }
    if (tclOOIntStubsPtr == NULL) {
	Tcl_AppendResult(interp, "TclOO internal stubs are not inialized");
	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");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand(interp, "pkgooa_stubsok", Pkgooa_StubsOKObjCmd, NULL, NULL);
    return TCL_OK;
}







>


|


















|
|






|



|



















|






81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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
};

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 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 initialized", (char *)NULL);
	return TCL_ERROR;
    }
    if (tclOOIntStubsPtr == NULL) {
	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");
    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
/*
 * 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
 *
 * 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.
 */



static Tcl_HashTable interpTokenMap;

static int interpTokenMapInitialised = 0;
#define MAX_REGISTERED_COMMANDS 2








static void
PkguaInitTokensHashTable(void)
{


    if (interpTokenMapInitialised) {
	return;
    }
    Tcl_InitHashTable(&interpTokenMap, TCL_ONE_WORD_KEYS);
    interpTokenMapInitialised = 1;
}

static void
PkguaFreeTokensHashTable(void)
{
    Tcl_HashSearch search;
    Tcl_HashEntry *entryPtr;


    for (entryPtr = Tcl_FirstHashEntry(&interpTokenMap, &search);
	    entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
	Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
    }
    interpTokenMapInitialised = 0;
}

static Tcl_Command *
PkguaInterpToTokens(
    Tcl_Interp *interp)
{
    int newEntry;
    Tcl_Command *cmdTokens;

    Tcl_HashEntry *entryPtr =
	    Tcl_CreateHashEntry(&interpTokenMap, 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) {
	    cmdTokens[newEntry] = NULL;
	}
	Tcl_SetHashValue(entryPtr, cmdTokens);
    } else {
	cmdTokens = (Tcl_Command *) Tcl_GetHashValue(entryPtr);
    }
    return cmdTokens;
}

static void
PkguaDeleteTokens(
    Tcl_Interp *interp)
{

    Tcl_HashEntry *entryPtr =
	    Tcl_FindHashEntry(&interpTokenMap, interp);

    if (entryPtr) {
	Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
	Tcl_DeleteHashEntry(entryPtr);
    }
}







|
|







<
<
<
<
<
<
<
<
<








<
<


>
>
|
>
|


>
>
>
>
>
>




>
>
|


|
|







>

|



|








>

|



|
|













>

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15









16
17
18
19
20
21
22
23


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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 © 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"










/*
 * 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.


 */

typedef struct ThreadSpecificData {
    int interpTokenMapInitialised;
    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 (tsdPtr->interpTokenMapInitialised) {
	return;
    }
    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(&tsdPtr->interpTokenMap, &search);
	    entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&search)) {
	Tcl_Free((char *) Tcl_GetHashValue(entryPtr));
    }
    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(&tsdPtr->interpTokenMap, (char *) interp, &newEntry);

    if (newEntry) {
	cmdTokens = (Tcl_Command *)
		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(&tsdPtr->interpTokenMap, (char *) 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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
PkguaEqObjCmd(
    ClientData 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;
    (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);


    if (len1 == len2) {
	result = (Tcl_UtfNcmp(str1, str2, len1) == 0);
    } else {
	result = 0;
    }
    Tcl_SetObjResult(interp, Tcl_NewIntObj(result));
    return TCL_OK;
}








|






|









>
>

|







116
117
118
119
120
121
122
123
124
125
126
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(
    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;
    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_NewIntObj(result));
    return TCL_OK;
}

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
PkguaQuoteObjCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument strings. */
{
    (void)dummy;

    if (objc != 2) {







|







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
PkguaQuoteObjCmd(
    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
 */

DLLEXPORT int
Pkgua_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code, cmdIndex = 0;
    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
     * for each interpreter.
     */

    PkguaInitTokensHashTable();

    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++] =
	    Tcl_CreateObjCommand(interp, "pkgua_quote", PkguaQuoteObjCmd,
		    NULL, NULL);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * Pkgua_SafeInit --







|







|





|







|
|
|
|

|







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
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;
    Tcl_Command *cmdTokens;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }

    /*
     * Initialize our Hash table, where we store the registered command tokens
     * for each interpreter.
     */

    PkguaInitTokensHashTable();

    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[0] =
	    Tcl_CreateObjCommand(interp, "pkgua_eq", PkguaEqObjCmd, &cmdTokens[0],
		    CommandDeleted);
    cmdTokens[1] =
	    Tcl_CreateObjCommand(interp, "pkgua_quote", PkguaQuoteObjCmd,
		    &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
#!/bin/sh
# install - install a program, script, or datafile

scriptversion=2020-07-26.22; # 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
#



|







1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh
# install - install a program, script, or datafile

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
# 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


chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=








>







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
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)
  -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.

  -s            $stripprog installed files.
  -S OPTION     $stripprog installed files using OPTION.

  -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








"

while test $# -ne 0; do
  case $1 in
    -c) ;;

    -C) copy_on_change=true;;







|




>

<
>






>
>
>
>
>
>
>
>







100
101
102
103
104
105
106
107
108
109
110
111
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 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 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 [email protected].
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
            exit 1;;
        esac
        shift;;

    -o) chowncmd="$chownprog $2"
        shift;;



    -s) stripcmd=$stripprog;;

    -S) stripcmd="$stripprog $2"
        shift;;

    -t)
        is_target_a_directory=always
        dst_arg=$2
        # Protect names problematic for 'test' and other utilities.
        case $dst_arg in







>
>


|







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) 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
  esac

  if test -n "$dir_arg"; then
    dst=$src
    dstdir=$dst
    test -d "$dstdir"
    dstdir_status=$?




  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







>
>
>
>







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
       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







      # 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 $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
            { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
          } ||
          { echo "$0: cannot unlink or rename $dst" >&2
            (exit 1); exit 1
          }
        } &&

        # Now rename the file to the real destination.







>
>
>
>
>
>
>














|

|







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 "$dst" 2>/dev/null ||
          { $doit $mvcmd -f "$dst" "$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
#!/bin/sh

########################################################################
### Parse Options
###

Gzip=:

SymOrLoc=""
Gz=""
Suffix=""

while true; do
    case $1 in
        -s | --symlinks  ) SymOrLoc="-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.







>
|





|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/sh

########################################################################
### Parse Options
###

Gzip=:
Sym=""
Loc=""
Gz=""
Suffix=""

while true; do
    case $1 in
        -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.
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    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/"

########################################################################
### Extract Target Names from Manual Page
###

# A sed script to parse the alternative names out of a man page.
#







|







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 "$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
    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"
    fi
done

########################################################################
exit 0







|





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 $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
    # 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],
		[directory containing tcl configuration (tclConfig.sh)]),
	    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 )







|

|







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,
	    AS_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    [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
    # 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],
		[directory containing tk configuration (tkConfig.sh)]),
	    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 )







|

|







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,
	    AS_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    [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
	    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 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` \
			; do
		    if test -f "$i/tkConfig.sh" ; then
			ac_cv_c_tkconfig="`(cd $i; pwd)`"
			break
		    fi
		done
	    fi







|


|
|







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/tk9.0 2>/dev/null` \
			`ls -d /usr/lib 2>/dev/null` \
			`ls -d /usr/lib64 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
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
#	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],
	    [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?])







|


<
<
<
<
<
<
<
<







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,
	AS_HELP_STRING([--enable-shared],
	    [build and link with shared libraries (default: on)]),
	[tcl_ok=$enableval], [tcl_ok=yes])








    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
#		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],
		[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







|







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,
	    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
#		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],
	    [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?])







|







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,
	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
#
#	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],
	    [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_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







|










|
|







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,
	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_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
#			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],
	    [use symlinks for the manpages (default: off)]),
	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],
	    [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")
    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],
	    [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")
    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







|

|
|




|






|













|






|



















>







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,
	AS_HELP_STRING([--enable-man-symlinks],
	    [use symlinks for the manpages (default: off)]),
	[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,
	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"])
    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,
	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"])
    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

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],
	    [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],
	    [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([
	    extern __attribute__((__visibility__("hidden"))) void f(void);

	    void f(void) {}], [f();], 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],
	    [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.








|








|












|

>
|
|












|







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,
	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,
	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_LINK_IFELSE([AC_LANG_PROGRAM([[
	    extern __attribute__((__visibility__("hidden"))) void f(void);
	    void f(void) {}]], [[f();]])],
	    [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,
	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
    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"
		;;
	esac

    ], [
	CFLAGS_OPTIMIZE=-O
	CFLAGS_WARNING=""
    ])







|







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 -fextended-identifiers"
		;;
	esac

    ], [
	CFLAGS_OPTIMIZE=-O
	CFLAGS_WARNING=""
    ])
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
	    SHLIB_SUFFIX=".so"
	    DL_OBJS="tclLoadDl.o"
	    DL_LIBS="-ldl"
	    LDFLAGS="$LDFLAGS -export-dynamic"
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;
	CYGWIN_*)
	    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([
		#ifdef __CYGWIN__
		    #error cygwin
		#endif
		], [],
		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"
		# The eval makes quoting arguments work.
		if cd ../win; eval ${CONFIG_SHELL-/bin/sh} ./configure $ac_configure_args; cd ../unix
		then :
		else
		    { echo "configure: error: configure failed for ../win" 1>&2; exit 1; }
		fi
	    fi
	    ;;
	dgux*)







|









<
<
<


|



|
|
|






|

|







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_*|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=""



	    AC_CACHE_CHECK(for Cygwin version of gcc,
		ac_cv_cygwin,
		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		#ifdef __CYGWIN__
		    #error cygwin
		#endif
		]], [[]])],
		[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 --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 --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*)
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
	            do64bit_ok=yes
	            SHLIB_LD="ld -64 -shared -rdata_shared"
	            CFLAGS="$CFLAGS -64"
	            LDFLAGS_ARCH="-64"
	        ])
	    ])
	    ;;
	Linux*|GNU*|NetBSD-Debian)
	    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"










	    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_TRY_LINK(,, 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
		])
	   ])








|













>
>
>
>
>
>
>
>
>
>








>
|







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
	            do64bit_ok=yes
	            SHLIB_LD="ld -64 -shared -rdata_shared"
	            CFLAGS="$CFLAGS -64"
	            LDFLAGS_ARCH="-64"
	        ])
	    ])
	    ;;
	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([[]], [[]])],
			    [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
		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"
	    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)
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
			    CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
			    do64bit_ok=yes
			]);;
		    i386)
			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)
			    CFLAGS=$hold_cflags])
			AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
			    CFLAGS="$CFLAGS -arch x86_64"
			    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) ' \
		    && 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_TRY_LINK(, [int i;], 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"
	    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],
		    [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)
		    AS_IF([test "$fat_32_64" = yes], [
			for v in CFLAGS CPPFLAGS LDFLAGS; do
			    eval $v'="$hold_'$v'"'
		        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)
			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"







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|

















|
|





|




|
|





>
>
>
>
>
>
>
>
>
>
>
>





|







>
|












>
|
|











|





|
















|
|
|
|
















|
|
|
|







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
		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"
	    ;;
























	Darwin-*)
	    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_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|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_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|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_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[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;]])],
			[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_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,
		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_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])
		    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_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"
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
	    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='ld -non_shared -expect_unresolved "*"'
	    ])
	    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}'])







|

|







1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
	    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='${CC} -shared'
	    ], [
	        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
	    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])
	    AS_IF([test $tcl_cv_ld_Bexport = yes], [
		LDFLAGS="$LDFLAGS -Wl,-Bexport"
	    ])
	    CC_SEARCH_FLAGS=""
	    LD_SEARCH_FLAGS=""
	    ;;







|







1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
	    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_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=""
	    ;;
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
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],
	    [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=""







|







1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
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,
	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
    # 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*) ;;
	    Darwin-*) ;;
	    IRIX*) ;;
	    Linux*|GNU*) ;;
	    NetBSD-*|OpenBSD-*) ;;
	    OSF1-V*) ;;
	    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=${UNSHARED_LIB_SUFFIX}








|
|




|



















|







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
    # 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_*|MINGW32_*|MSYS_*) ;;
	    HP-UX*) ;;
	    Darwin-*) ;;
	    IRIX*) ;;
	    Linux*|GNU*) ;;
	    NetBSD-*|OpenBSD-*) ;;
	    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)"'
            DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)"
        ], [
            INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"'
        ])
    ], [
        LIB_SUFFIX=${UNSHARED_LIB_SUFFIX}

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
    # 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}"])
    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.

	AC_CACHE_CHECK(for cast to union support,
	    tcl_cv_cast_to_union,
	    AC_TRY_COMPILE([],
	    [
		  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






















    AC_CHECK_HEADER(stdbool.h, [AC_DEFINE(HAVE_STDBOOL_H, 1, [Do we have <stdbool.h>?])],)




    # 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(LDFLAGS)
    AC_SUBST(LDFLAGS_DEBUG)
    AC_SUBST(LDFLAGS_OPTIMIZE)
    AC_SUBST(CC_SEARCH_FLAGS)
    AC_SUBST(LD_SEARCH_FLAGS)








|
|
|

|
|
|
<
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>













>







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
    # 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}"])
    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.

    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
    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
#
# 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)
])

#--------------------------------------------------------------------
# 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







<
<









<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<















|







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
#
# Arguments:
#	none
#
# Results:
#
#	Defines some of the following vars:


#		NO_STRING_H
#		NO_SYS_WAIT_H
#		NO_DLFCN_H
#		HAVE_SYS_PARAM_H
#		HAVE_STRING_H ?
#
#--------------------------------------------------------------------

AC_DEFUN([SC_MISSING_POSIX_HEADERS], [
































    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_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
#--------------------------------------------------------------------

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")
	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")
	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"







|









|







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
#--------------------------------------------------------------------

AC_DEFUN([SC_PATH_X], [
    AC_PATH_X
    not_really_there=""
    if test "$no_x" = ""; then
	if test "$x_includes" = ""; then
	    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_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
#		HAVE_TM_TZADJ
#		HAVE_TIMEZONE_VAR
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TIME_HANDLER], [
    AC_CHECK_HEADERS(sys/time.h)
    AC_HEADER_TIME

    AC_CHECK_FUNCS(gmtime_r localtime_r mktime)

    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)])

    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)])

    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;
	    timezone += 1;
	    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;
		timezone += 1;
		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.
#
# Arguments:
#	None.
#
# Results:
#
#	Sets the following vars:







|




|
|
>





|
|
>









|
>
|

|
|







|
>
|

|
|










|
>
|







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
#		HAVE_TM_TZADJ
#		HAVE_TIMEZONE_VAR
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TIME_HANDLER], [
    AC_CHECK_HEADERS(sys/time.h)
    AC_CHECK_HEADERS_ONCE([sys/time.h])

    AC_CHECK_FUNCS(gmtime_r localtime_r mktime)

    AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
	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_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_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])])
    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_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])])
	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), 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
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		_ISOC99_SOURCE
#		_LARGEFILE64_SOURCE
#		_LARGEFILE_SOURCE64
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_EARLY_FLAG],[
    AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),

	AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
	    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)))
    if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
	AC_DEFINE($1, 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(_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

#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_64BIT_FLAGS], [
    AC_MSG_CHECKING([for 64-bit integer type])
    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})])
    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}])

	# Now check for auxiliary declarations

















	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)])
	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)])
	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)])
	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
	    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
	    AC_MSG_RESULT([yes])







|
|





>
|
<
|
|
|

|









>
>


<
<



















<

<

>




|


<
<
<



|
|
|




<
<
|
<

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
|





|
|
|
|




<
<
<
<
<
<
<
<



|
|
|







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
# Arguments:
#	None
#
# Results:
#
#	Might define the following vars:
#		_ISOC99_SOURCE
#		_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]])],
	    [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[[#define ]$1[ ]m4_default([$4],[1])[

]$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, 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);])


    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

#		HAVE_STRUCT_DIRENT64, HAVE_DIR64

#		HAVE_TYPE_OFF64_T
#		_TIME_BITS
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_64BIT_FLAGS], [
    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 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_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_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_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_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_CHECK_FUNCS(open64 lseek64)
	AC_MSG_CHECKING([for off64_t])
	AC_CACHE_VAL(tcl_cv_type_off64_t,[
	    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
	    AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
	    AC_MSG_RESULT([yes])
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
#	Will define the following vars:
#		TCL_CFGVAL_ENCODING
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_CFG_ENCODING], [
    AC_ARG_WITH(encoding,
	AC_HELP_STRING([--with-encoding],
	    [encoding for configuration values (default: utf-8)]),
	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?])







|

|







2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
#	Will define the following vars:
#		TCL_CFGVAL_ENCODING
#
#--------------------------------------------------------------------

AC_DEFUN([SC_TCL_CFG_ENCODING], [
    AC_ARG_WITH(encoding,
	AS_HELP_STRING([--with-encoding],
	    [encoding for configuration values (default: utf-8)]),
	[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
#
#--------------------------------------------------------------------

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([[
#include <stdlib.h>
#include <string.h>
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







|


|
|







2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
#
#--------------------------------------------------------------------

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_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]))
	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

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([
	#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_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([
	    #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_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







|

|










|






|

|










|







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

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_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_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_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_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

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([
	#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_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([
	    #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_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([
		#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_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







|

|







|






|

|







|






|

|





|







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

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_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_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_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_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_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_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
#		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([
	#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_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([
	    #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_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







|


|






|






|


|






|







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
#		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_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_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_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_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
#		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([
	#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_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([
	    #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_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







|


|






|






|


|






|







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
#		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_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_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_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_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
#		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([
	#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_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([
	    #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_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







|


|






|






|


|






|







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
#		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_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_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_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_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
#		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([
	#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_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([
	    #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_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







|


|






|






|


|






|







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
#		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_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_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_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_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
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
#	Locate a zip encoder installed on the system path, or none.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:

#		ZIP_PROG
#       ZIP_PROG_OPTIONS
#       ZIP_PROG_VFSSEARCH
#       ZIP_INSTALL_OBJS
#------------------------------------------------------------------------

AC_DEFUN([SC_ZIPFS_SUPPORT], [

    ZIP_PROG=""
    ZIP_PROG_OPTIONS=""
    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







>
|






>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
#	Locate a zip encoder installed on the system path, or none.
#
# Arguments:
#	none
#
# Results:
#	Substitutes the following vars:
#       MACHER_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
3036
3037
3038
3039
3040
3041
3042

3043
3044
3045
3046
3047
3048
3049
3050
3051
        # 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)
])

# Local Variables:
# mode: autoconf
# End:







>









3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
        # 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
# 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/
Version: @TCL_VERSION@@TCL_PATCH_LEVEL@
Requires.private: zlib >= 1.2.3, libtommath >= 1.2.0
Libs: -L${libdir} @TCL_LIB_FLAG@ @TCL_STUB_LIB_FLAG@
Libs.private: @TCL_LIBS@
Cflags: -I${includedir}







<



|

|


|
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@


Name: Tool Command Language
Description: Tcl is a powerful, easy-to-learn dynamic programming language, suitable for a wide range of uses.
URL: https://www.tcl-lang.org/
Version: @TCL_VERSION@@TCL_PATCH_LEVEL@
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} @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
# 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
Release:       2
License:       BSD
Group:         Development/Languages
Source:        http://prdownloads.sourceforge.net/tcl/tcl%{version}-src.tar.gz
URL:           http://www.tcl.tk/
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






|




|







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.0b2
Release:       2
License:       BSD
Group:         Development/Languages
Source:        http://prdownloads.sourceforge.net/tcl/tcl%{version}-src.tar.gz
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
 * 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"










#ifdef TCL_TEST
extern Tcl_PackageInitProc Tcltest_Init;
extern Tcl_PackageInitProc Tcltest_SafeInit;
#endif /* TCL_TEST */

#ifdef TCL_XT_TEST
extern void                XtToolkitInitialize(void);
extern Tcl_PackageInitProc 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.
 */







<
<

>
>
>
>
>
>
>
>
>


|
|




|







8
9
10
11
12
13
14


15
16
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.
 */



#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 */

#ifdef TCL_XT_TEST
extern void                XtToolkitInitialize(void);
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
{
#ifdef TCL_XT_TEST
    XtToolkitInitialize();
#endif

#ifdef TCL_LOCAL_MAIN_HOOK
    TCL_LOCAL_MAIN_HOOK(&argc, &argv);
#else

    TclZipfs_AppHook(&argc, &argv);
#endif

    Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
    return 0;			/* Needed only to prevent compiler warning. */
}








|
>







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);
#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
 *----------------------------------------------------------------------
 */

int
Tcl_AppInit(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    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);
#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
     * 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);
#else
    (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,
	    Tcl_NewStringObj("~/.tclshrc", -1), TCL_GLOBAL_ONLY);
#endif




    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|













|















|









<

<
|

<
|


>
>
>










114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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) {
	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_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_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

#define INITFILENAME "tclshrc.tcl"
#else

#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
/* ../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'. */
#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. */
#undef HAVE_CFMAKERAW

/* Define to 1 if you have the `chflags' function. */
#undef HAVE_CHFLAGS

/* 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
   you don't. */
#undef HAVE_DECL_GETHOSTBYADDR_R

/* 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
   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. */
#undef HAVE_FREEADDRINFO

/* Do we have fts functions? */
#undef HAVE_FTS

/* Define to 1 if you have the `gai_strerror' function. */
#undef HAVE_GAI_STRERROR

/* Define to 1 if you have the `getaddrinfo' function. */
#undef HAVE_GETADDRINFO

/* Define to 1 if you have the `getattrlist' function. */
#undef HAVE_GETATTRLIST

/* 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






<
<
<






|





|


|


|











|



|



|









|





|


|


|


|







1
2
3
4
5
6



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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




/* 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'. */
#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. */
#undef HAVE_CFMAKERAW

/* Define to 1 if you have the 'chflags' function. */
#undef HAVE_CHFLAGS

/* 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
   you don't. */
#undef HAVE_DECL_GETHOSTBYADDR_R

/* 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
   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. */
#undef HAVE_FREEADDRINFO

/* Do we have fts functions? */
#undef HAVE_FTS

/* Define to 1 if you have the 'gai_strerror' function. */
#undef HAVE_GAI_STRERROR

/* Define to 1 if you have the 'getaddrinfo' function. */
#undef HAVE_GETADDRINFO

/* Define to 1 if you have the 'getattrlist' function. */
#undef HAVE_GETATTRLIST

/* 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

/* 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. */
#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. */
#undef HAVE_GMTIME_R

/* Compiler support for module scope symbols */
#undef HAVE_HIDDEN

/* Do we have the intptr_t type? */
#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. */
#undef HAVE_LOCALTIME_R

/* 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. */
#undef HAVE_MKSTEMP

/* 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. */
#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 `pthread_atfork' function. */
#undef HAVE_PTHREAD_ATFORK

/* 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 <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'. */
#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'. */
#undef HAVE_STRUCT_IN6_ADDR

/* 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'. */
#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_blocks' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_BLOCKS

/* 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








|




















|





|











|


|


<
<
<
|


|


|











|


|
|

>
>
>
|
>
>
>
>
>
>
|

|


|













>
>
>










<
<
<
|





|


|


|


|
|

|
|

|
|







105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252

/* 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. */
#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. */
#undef HAVE_GMTIME_R

/* Compiler support for module scope symbols */
#undef HAVE_HIDDEN

/* 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. */
#undef HAVE_LOCALTIME_R

/* Define to 1 if you have the 'lseek64' function. */
#undef HAVE_LSEEK64




/* Define to 1 if you have the 'mkstemp' function. */
#undef HAVE_MKSTEMP

/* 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. */
#undef HAVE_OPEN64

/* 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 '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. */
#undef HAVE_PTHREAD_ATFORK

/* 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 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'. */
#undef HAVE_STRUCT_IN6_ADDR

/* 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'. */
#undef HAVE_STRUCT_SOCKADDR_STORAGE

/* 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_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

/* 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? */
#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. */



#undef HAVE_WAITPID

/* Is weak import available? */
#undef HAVE_WEAK_IMPORT

/* Is there an installed zlib? */
#undef HAVE_ZLIB







|





|
>
>
>







288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311

/* 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

/* 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 '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
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

/* 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 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 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 uname() */
#undef NO_UNAME

/* Do we have a usable 'union wait'? */
#undef NO_UNION_WAIT








<
<
<





>
>
>










|
|

|
|




<
<
<








>
>
>







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

/* Is kqueue(2) supported? */
#undef NOTIFIER_KQUEUE

/* Is Darwin CoreFoundation unavailable for 64-bit? */
#undef NO_COREFOUNDATION_64




/* 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 memmove()? */
#undef NO_MEMMOVE

/* Do we have mknod() */
#undef NO_MKNOD

/* Do we have realpath() */
#undef NO_REALPATH




/* 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 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

/* 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. */


#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







|
>
>







399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415

/* Define to the version of this package. */
#undef PACKAGE_VERSION

/* Is this a static build? */
#undef STATIC_BUILD

/* 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

/* 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

/* 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 _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




/* 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.  */

#ifndef __CHAR_UNSIGNED__
# undef __CHAR_UNSIGNED__
#endif

/* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t

/* 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. */
#undef mode_t

/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t

/* Define to `unsigned int' if <sys/types.h> does not 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. */
#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

    #endif /* _TCLCONFIG */







<
<
<



<
<
<



<
<
<






<
<
<

















>
>
>







<
<
<











>
>
>







|
>




|


|





<
<
<
|


|


|





|


<
<
<




|
|
>

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

/* 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




/* Tcl with external libtommath */
#undef TCL_WITH_EXTERNAL_TOMMATH




/* Is getcwd Posix-compliant? */
#undef USEGETWD




/* Are we building with DTrace support? */
#undef USE_DTRACE

/* Should we use FIONBIO? */
#undef USE_FIONBIO




/* 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




/* # 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 your compiler does not
   predefine this macro.  */
#ifndef __CHAR_UNSIGNED__
# undef __CHAR_UNSIGNED__
#endif

/* 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
   calls it, or to nothing if 'inline' is not supported under any name.  */
#ifndef __cplusplus
#undef inline
#endif




/* Define to 'int' if <sys/types.h> does not define. */
#undef mode_t

/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t

/* 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 as 'int' if <sys/types.h> doesn't define. */
#undef uid_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_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
/*
 * 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 <[email protected]>
 *
 * 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







|
|







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 © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2016 Lucio Andrés Illanes Albornoz <[email protected]>
 *
 * 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
    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. */
    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







|







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. */
    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
				/* 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. */
#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. */

} 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.
 */

#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.
 *
 *----------------------------------------------------------------------
 */

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.
 *
 *----------------------------------------------------------------------
 */

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







|













>










<




|

|







|







|
|




|
|

<
<
<
|

|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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
				 * 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		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 implementation.
 */

#include "tclUnixNotfy.c"

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *
 *----------------------------------------------------------------------
 */

void *
TclpInitNotifier(void)
{



    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    PlatformEventsInit();
    return tsdPtr;
}
































/*
 *----------------------------------------------------------------------
 *
 * 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
 *	- 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
PlatformEventsControl(
    FileHandler *filePtr,
    ThreadSpecificData *tsdPtr,
    int op,
    int isNew)
{
    struct epoll_event newEvent;
    struct PlatformEventData *newPedPtr;
    struct stat 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;
	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
     * added or deleted from the list of FileHandlers associated with regular
     * files belonging to tsdPtr.
     */

    if (fstat(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;
   } else if (epoll_ctl(tsdPtr->eventsFd, op, filePtr->fd, &newEvent) == -1) {

	Tcl_Panic("epoll_ctl: %s", strerror(errno));
   }
}



/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsFinalize --
 *
 *	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:







|








|









|
>








|




|

>
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
>
|
<
>
|
|
|
>
|
>



|







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
 *	- 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.
 *
 *----------------------------------------------------------------------
 */

static void
PlatformEventsControl(
    FileHandler *filePtr,
    ThreadSpecificData *tsdPtr,
    int op,
    int isNew)
{
    struct epoll_event newEvent;
    struct PlatformEventData *newPedPtr;
    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;
	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
     * added or deleted from the list of FileHandlers associated with regular
     * files belonging to tsdPtr.
     */

    if (TclOSfstat(filePtr->fd, &fdStat) == -1) {
	Tcl_Panic("fstat: %s", strerror(errno));
    }

   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;

	    default:
		Tcl_Panic("epoll_ctl: %s", strerror(errno));
	}
    }
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * 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:
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
 *
 *	tsdPtr->notifierMutex is destroyed.
 *
 *----------------------------------------------------------------------
 */

void
PlatformEventsFinalize(
	void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    pthread_mutex_lock(&tsdPtr->notifierMutex);
#ifdef HAVE_EVENTFD
    if (tsdPtr->triggerEventFd) {
	close(tsdPtr->triggerEventFd);







|
|







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
 *
 *	tsdPtr->notifierMutex is destroyed.
 *
 *----------------------------------------------------------------------
 */

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
 *	  PlatformEventsControl().
 *	- readyEvents and maxReadyEvents are initialised with 512
 *	  epoll_events.
 *
 *----------------------------------------------------------------------
 */

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));
#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 * sizeof(tsdPtr->readyEvents[0]));
    }
    LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
}

/*
 *----------------------------------------------------------------------







|









|




















|







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.
 *
 *----------------------------------------------------------------------
 */

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));
#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 * sizeof(tsdPtr->readyEvents[0]));
    }
    LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);
}

/*
 *----------------------------------------------------------------------
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

int
PlatformEventsTranslate(
    struct epoll_event *eventPtr)
{
    int mask;

    mask = 0;
    if (eventPtr->events & (EPOLLIN | EPOLLHUP)) {







|







387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

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
 *	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
PlatformEventsWait(
    struct epoll_event *events,
    size_t numEvents,
    struct timeval *timePtr)
{
    int numFound;
    struct timeval tv0, tv1, tv_delta;







|







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.
 *
 *----------------------------------------------------------------------
 */

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
     */

    if (!timePtr) {
	timeout = -1;
    } else if (!timePtr->tv_sec && !timePtr->tv_usec) {
	timeout = 0;
    } else {
	timeout = (int)timePtr->tv_sec * 1000;
	if (timePtr->tv_usec) {
	    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);
    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;
	}
    }




    return numFound;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateFileHandler --
 *
 *	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(
    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. */
{
    int isNew;

    if (tclNotifierHooks.createFileHandlerProc) {
	tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
	return;
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	FileHandler *filePtr;

	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;
	    isNew = 1;
	} else {
	    isNew = 0;
	}
	filePtr->proc = proc;
	filePtr->clientData = clientData;
	filePtr->mask = mask;

	PlatformEventsControl(filePtr, tsdPtr,
		isNew ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 *
 *	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(
    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);

	/*
	 * 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;
	    }
	    if (filePtr->fd == fd) {
		break;
	    }
	}

	/*
	 * Update the check masks for this file.
	 */

	PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_DEL, 0);
	if (filePtr->pedPtr) {
	    Tcl_Free(filePtr->pedPtr);
	}

	/*
	 * Clean up information in the callback record.
	 */

	if (prevPtr == NULL) {
	    tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
	} else {
	    prevPtr->nextPtr = filePtr->nextPtr;
	}
	Tcl_Free(filePtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 *
 *	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.
 *
 *	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. */
{
    if (tclNotifierHooks.waitForEventProc) {
	return tclNotifierHooks.waitForEventProc(timePtr);
    } else {
	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;
	int 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
	 * 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->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;
	}

	/*
	 * 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().
	 */

	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.
	     */

	    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;
	}

	/*
	 * 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;
	}

	/*
	 * 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.
	 */

	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,
			sizeof(eventFdVal));
		if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) {
		    Tcl_Panic(
			    "Tcl_WaitForEvent: read from %p->triggerEventFd: %s",
			    (void *) 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)) {
		    Tcl_Panic(
			    "Tcl_WaitForEvent: read from %p->triggerPipe[0]: %s",
			    (void *) tsdPtr, strerror(errno));
		}
		continue;
	    }
#endif /* HAVE_EVENTFD */
	    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.
	     */

	    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;
    }
}




























































#endif /* NOTIFIER_EPOLL && TCL_THREADS */


#endif /* !HAVE_COREFOUNDATION */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|

|










|










>
>
>
>






|















|







|

<
<
<
<
<
<
|
|
|
<
<
<
<
|
<
|
|
|
|
|
|
<
<
<
|
|
|
|

|
|
|
|
<



|

















|



<
<
<
<
|
|

|
|
|

<
|
|
|
<
<
<
<
|

|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|
<





|


|















|


<
<
<
|
<
|
<
>
|
>
|
|
<
|
<
|
|
|
|
|

|
|
|
<
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
<
|

|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
<
|

|
|
|
|
>
|
|

|
|
>
|
<
|
<
|
|
|
|
|

|
|
>
|
|
|
<
|
|
|
|
|

|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>









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;
	if (timePtr->tv_usec) {
	    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);
    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;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
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. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{






    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);
    int isNew = (filePtr == NULL);






    if (isNew) {
	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;

    PlatformEventsControl(filePtr, tsdPtr,
	    isNew ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, isNew);
}


/*
 *----------------------------------------------------------------------
 *
 * 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
TclpDeleteFileHandler(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{




    FileHandler *filePtr, *prevPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    /*
     * Find the entry for the given file (and return if there isn't one).
     */


    filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
    if (filePtr == NULL) {
	return;




    }

    /*
     * Update the check masks for this file.
     */

    PlatformEventsControl(filePtr, tsdPtr, EPOLL_CTL_DEL, 0);
    if (filePtr->pedPtr) {
	Tcl_Free(filePtr->pedPtr);
    }

    /*
     * Clean up information in the callback record.
     */

    if (prevPtr == NULL) {
	tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
    } else {
	prevPtr->nextPtr = filePtr->nextPtr;
    }
    Tcl_Free(filePtr);

}

/*
 *----------------------------------------------------------------------
 *
 * TclpWaitForEvent --
 *
 *	This function is called by Tcl_DoOneEvent to wait for new events on
 *	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
TclpWaitForEvent(
    const Tcl_Time *timePtr)	/* Maximum block time, or NULL. */
{



    FileHandler *filePtr;

    Tcl_Time vTime;

    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. */

    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 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->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 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;
	}

	/*
	 * 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));

	    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 (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 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]);
#ifdef HAVE_EVENTFD
	if (filePtr->fd == tsdPtr->triggerEventFd) {
	    uint64_t eventFdVal;

	    i = read(tsdPtr->triggerEventFd, &eventFdVal, sizeof(eventFdVal));

	    if ((i != sizeof(eventFdVal)) && (errno != EAGAIN)) {

		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)) {

		Tcl_Panic("%s: read from %p->triggerPipe[0]: %s",
			"Tcl_WaitForEvent", tsdPtr, strerror(errno));
	    }
	    continue;
	}
#endif /* HAVE_EVENTFD */
	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.
	 */

	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;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
/*
 * 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 <[email protected]>
 *
 * 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








|
|







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 © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2016 Lucio Andrés Illanes Albornoz <[email protected]>
 *
 * 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
/*
 * This structure is used to keep track of the notifier info for a registered
 * file.
 */

struct PlatformEventData;
typedef struct FileHandler {
    int fd;

    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. */
    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







|
>







|







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;			/* 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. */
    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
				/* 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. */
    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. */

} 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.
 *
 *----------------------------------------------------------------------
 */

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.
 *
 *----------------------------------------------------------------------
 */

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







|







>










<
<



|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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
				 * 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 int		PlatformEventsTranslate(struct kevent *eventPtr);
static int		PlatformEventsWait(struct kevent *events,
			    size_t numEvents, struct timeval *timePtr);



/*















 * Incorporate the base notifier implementation.















 */














#include "tclUnixNotfy.c"












/*
 *----------------------------------------------------------------------
 *
 * 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
 *	  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
PlatformEventsControl(
    FileHandler *filePtr,
    ThreadSpecificData *tsdPtr,
    int op,
    int isNew)
{
    int numChanges;
    struct kevent changeList[2];
    struct PlatformEventData *newPedPtr;
    struct stat fdStat;

    if (isNew) {
        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) {
	Tcl_Panic("fstat: %s", strerror(errno));
    } else if ((fdStat.st_mode & S_IFMT) == S_IFREG) {



	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,
		    EVFILT_READ, op, 0, 0, filePtr->pedPtr);
	    numChanges++;
	}
	if (filePtr->mask & TCL_WRITABLE) {
	    EV_SET(&changeList[numChanges], (uintptr_t)filePtr->fd,
		    EVFILT_WRITE, op, 0, 0, filePtr->pedPtr);
	    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,
		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,
		NULL);
	if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1)
		&& (errno != ENOENT)) {
	    Tcl_Panic("kevent: %s", strerror(errno));
	}
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsFinalize --
 *
 *	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:







|









|


|
>
|
|
|










|

|
>
>
>


















|




|



|

















|





|












|







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
 *	  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.)
 *
 *----------------------------------------------------------------------
 */

static void
PlatformEventsControl(
    FileHandler *filePtr,
    ThreadSpecificData *tsdPtr,
    int op,
    int isNew)
{
    int numChanges;
    struct kevent changeList[2];
    struct PlatformEventData *newPedPtr;
    Tcl_StatBuf fdStat;

    if (isNew) {
	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 (TclOSfstat(filePtr->fd, &fdStat) == -1) {
	Tcl_Panic("fstat: %s", strerror(errno));
    } 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,
		    EVFILT_READ, op, 0, 0, filePtr->pedPtr);
	    numChanges++;
	}
	if (filePtr->mask & TCL_WRITABLE) {
	    EV_SET(&changeList[numChanges], (uintptr_t) filePtr->fd,
		    EVFILT_WRITE, op, 0, 0, filePtr->pedPtr);
	    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,
		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,
		NULL);
	if ((kevent(tsdPtr->eventsFd, changeList, 1, NULL, 0, NULL) == -1)
		&& (errno != ENOENT)) {
	    Tcl_Panic("kevent: %s", strerror(errno));
	}
	break;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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:
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
 *
 *	tsdPtr->notifierMutex is destroyed.
 *
 *----------------------------------------------------------------------
 */

void
PlatformEventsFinalize(
    void)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    pthread_mutex_lock(&tsdPtr->notifierMutex);
    if (tsdPtr->triggerPipe[0]) {
	close(tsdPtr->triggerPipe[0]);
	tsdPtr->triggerPipe[0] = -1;







|
|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
 *
 *	tsdPtr->notifierMutex is destroyed.
 *
 *----------------------------------------------------------------------
 */

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
	Tcl_Panic("pthread_mutex_destroy: %s", strerror(errno));
    }
}

/*
 *----------------------------------------------------------------------
 *
 * PlatformEventsInit --


 *
 *	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.
 *
 * 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)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    int i, fdFl;
    FileHandler *filePtr;

    errno = pthread_mutex_init(&tsdPtr->notifierMutex, NULL);
    if (errno) {







|
>
>






|
















|
|







300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
	Tcl_Panic("pthread_mutex_destroy: %s", strerror(errno));
    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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:
 *	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 *
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
	}
    }
    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->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 * sizeof(tsdPtr->readyEvents[0]));
    }
    LIST_INIT(&tsdPtr->firstReadyFileHandlerPtr);


}

/*
 *----------------------------------------------------------------------
 *
 * 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
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.







|




|
|



>
>



















|




















|







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
	}
    }
    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->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 * 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.
 *
 *----------------------------------------------------------------------
 */

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
 *	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
PlatformEventsWait(
    struct kevent *events,
    size_t numEvents,
    struct timeval *timePtr)
{
    int numFound;
    struct timeval tv0, tv1, tv_delta;







|







431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
 *	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.
 *
 *----------------------------------------------------------------------
 */

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
	if (!timercmp(&tv_delta, timePtr, >)) {
	    timersub(timePtr, &tv_delta, timePtr);
	} else {
	    timePtr->tv_sec = 0;
	    timePtr->tv_usec = 0;
	}
    }




    return numFound;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateFileHandler --
 *
 *	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(
    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. */
{
    int isNew;

    if (tclNotifierHooks.createFileHandlerProc) {
	tclNotifierHooks.createFileHandlerProc(fd, mask, proc, clientData);
	return;
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
	FileHandler *filePtr;

	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;
	    isNew = 1;
	} else {
	    isNew = 0;
	}
	filePtr->proc = proc;
	filePtr->clientData = clientData;
	filePtr->mask = mask;

	PlatformEventsControl(filePtr, tsdPtr, EV_ADD, isNew);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 *
 *	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(
    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);

	/*
	 * 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;
	    }
	    if (filePtr->fd == fd) {
		break;
	    }
	}

	/*
	 * Update the check masks for this file.
	 */

	PlatformEventsControl(filePtr, tsdPtr, EV_DELETE, 0);
	if (filePtr->pedPtr) {
	    Tcl_Free(filePtr->pedPtr);
	}

	/*
	 * Clean up information in the callback record.
	 */

	if (prevPtr == NULL) {
	    tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
	} else {
	    prevPtr->nextPtr = filePtr->nextPtr;
	}
	Tcl_Free(filePtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 *
 *	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.
 *
 *	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. */
{
    if (tclNotifierHooks.waitForEventProc) {
	return tclNotifierHooks.waitForEventProc(timePtr);
    } else {
	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;
	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
	 * 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->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;
	}

	/*
	 * 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;
	    }

	    /*
	     * 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));

		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 (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.
	 */

	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;
	    }

	    /*
	     * 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));

		fileEvPtr->header.proc = FileHandlerEventProc;
		fileEvPtr->fd = filePtr->fd;
		Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL);
	    }
	    filePtr->readyMask |= mask;
	}
	return 0;
    }
}




























































#endif /* NOTIFIER_KQUEUE && TCL_THREADS */


#endif /* !HAVE_COREFOUNDATION */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>
>
>
>






|















|







|

<
<
<
<
<
<
|
|
|
<
<
<
<
|
<
|
|
|
|
|
|
<
<
<
|
|
|
|

|
|
|
<



|

















|



|
<
<
<
|
<

|
|
|

<
|
|
|
<
<
<
<
|

|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|
<





|


|















|
|

<
<
<
|
|
|
<
>
|
>
|
|
<
|
<
|
|
|
|
|
|

|
|
|
<
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>









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
	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;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
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. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{






    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);
    int isNew = (filePtr == NULL);






    if (isNew) {
	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;

    PlatformEventsControl(filePtr, tsdPtr, EV_ADD, isNew);
}


/*
 *----------------------------------------------------------------------
 *
 * 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
TclpDeleteFileHandler(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);



    FileHandler *filePtr, *prevPtr;


    /*
     * Find the entry for the given file (and return if there isn't one).
     */


    filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
    if (filePtr == NULL) {
	return;




    }

    /*
     * Update the check masks for this file.
     */

    PlatformEventsControl(filePtr, tsdPtr, EV_DELETE, 0);
    if (filePtr->pedPtr) {
	Tcl_Free(filePtr->pedPtr);
    }

    /*
     * Clean up information in the callback record.
     */

    if (prevPtr == NULL) {
	tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
    } else {
	prevPtr->nextPtr = filePtr->nextPtr;
    }
    Tcl_Free(filePtr);

}

/*
 *----------------------------------------------------------------------
 *
 * TclpWaitForEvent --
 *
 *	This function is called by Tcl_DoOneEvent to wait for new events on
 *	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
TclpWaitForEvent(
    const Tcl_Time *timePtr)	/* Maximum block time, or NULL. */
{



    FileHandler *filePtr;
    int mask;
    Tcl_Time vTime;

    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. */

    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 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->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().
     */

    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.
	 */

	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;
    }

    /*
     * 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;
    }

    /*
     * 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",
			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.
	 */

	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;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
/*
 * 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
 *	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
 * 30159 Hannover, Germany
 */

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <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
/*
 * 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 © 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 © 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
    /*
     * 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;
	}
    }

    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);
    if (mp->entry == NULL) {
	free(mp->name);
	free(mp);
	errvalid++;
	strcpy(errbuf, "dlopen: ");
	strcat(errbuf, path);
	strcat(errbuf, ": ");







|



















|







118
119
120
121
122
123
124
125
126
127
128
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;
	}
    }

    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);
    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
	    mp->cdtors->init();
	    mp->cdtors++;
	}
    } else {
	errvalid = 0;
    }

    return (void *) mp;
}

/*
 * Attempt to decipher an AIX loader error message and append it to our static
 * error message buffer.
 */








|







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;
}

/*
 * Attempt to decipher an AIX loader error message and append it to our static
 * error message buffer.
 */

Changes to unix/tclLoadDl.c.

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.
 *
 * 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






|







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 © 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
104
105
106
107
108
109
110
111




112
113
114
115
116
117
118
	 * 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);




	/*
	 * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
	 */
	handle = dlopen(native, dlopenflags);
	Tcl_DStringFree(&ds);
    }








|
>
>
>
>







104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
	 * string the user gave us which hopefully refers to a file on the
	 * binary path.
	 */

	Tcl_DString ds;
	const char *fileName = TclGetString(pathPtr);

	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
    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;
				/* 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);




    proc = dlsym(handle, native);	/* INTL: Native. */
    if (proc == NULL) {
	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "_");
	native = Tcl_DStringAppend(&newName, native, -1);
	proc = dlsym(handle, native);	/* INTL: Native. */
	Tcl_DStringFree(&newName);
    }
#ifdef __cplusplus
    if (proc == NULL) {
	char buf[32];
	sprintf(buf, "%d", (int)Tcl_DStringLength(&ds));
	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "__Z");
	Tcl_DStringAppend(&newName, buf, -1);
	Tcl_DStringAppend(&newName, Tcl_DStringValue(&ds), -1);
	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) {







|










|
>
>
>
>




|






|


|
|







168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
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 = 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.
     */

    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, TCL_INDEX_NONE);
	proc = dlsym(handle, native);	/* INTL: Native. */
	Tcl_DStringFree(&newName);
    }
#ifdef __cplusplus
    if (proc == NULL) {
	char buf[32];
	snprintf(buf, sizeof(buf), "%d", (int)Tcl_DStringLength(&ds));
	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "__Z");
	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
	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);
	}
    }
    return proc;
}

/*
 *----------------------------------------------------------------------







|







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,
		    (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
				 * 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:
 */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








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);
}





























/*
 * 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
/*
 * 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 ([email protected]).
 *
 * Copyright (c) 1995 Apple Computer, Inc.
 * Copyright (c) 2001-2007 Daniel A. Steffen <[email protected]>
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"









|
|







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 ([email protected]).
 *
 * Copyright © 1995 Apple Computer, Inc.
 * Copyright © 2001-2007 Daniel A. Steffen <[email protected]>
 *
 * 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
 */

#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
static const char *
DyldOFIErrorMsg(
    int 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:







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 */

#if TCL_DYLD_USE_NSMODULE || defined(TCL_LOAD_FROM_MEMORY)
static const char *
DyldOFIErrorMsg(
    int 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:
180
181
182
183
184
185
186
187

188



189
190
191
192
193
194
195
    /*
     * 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_DYLD_USE_DLFCN
    /*
     * Use (RTLD_NOW|RTLD_LOCAL) as default, see [Bug #3216070]
     */

    if (flags & TCL_LOAD_GLOBAL) {







|
>
|
>
>
>







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
    /*
     * 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);
    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) {
249
250
251
252
253
254
255

256


257

258
259
260
261
262
263
264
		 * 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)) 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 {







>
|
>
>
|
>







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)) {
			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
	*loadHandle = newHandle;
	result = TCL_OK;
    } else {
	Tcl_Obj *errObj;

	TclNewObj(errObj);
	if (errMsg != NULL) {
	    Tcl_AppendToObj(errObj, errMsg, -1);
	}
#if TCL_DYLD_USE_NSMODULE
	if (objFileImageErrMsg) {
	    Tcl_AppendPrintfToObj(errObj,
		    "\nNSCreateObjectFileImageFromFile() error: %s",
		    objFileImageErrMsg);
	}







|







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, 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
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;
    const char *errMsg = NULL;
    Tcl_DString ds;
    const char *native;

    native = Tcl_UtfToExternalDString(NULL, symbol, -1, &ds);




    if (dyldLoadHandle->dlHandle) {
#if TCL_DYLD_USE_DLFCN
	proc = (Tcl_PackageInitProc *)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);
	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







|




|
>
>
>
>


|















|







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_LibraryInitProc *proc = NULL;
    const char *errMsg = NULL;
    Tcl_DString ds;
    const char *native;

    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_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, 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
		NSLinkEditError(&editError, &errorNumber, &errorName, &errMsg);
	    }
	} else if (dyldLoadHandle->modulePtr) {
	    nsSymbol = NSLookupSymbolInModule(
		    dyldLoadHandle->modulePtr->module, native);
	}
	if (nsSymbol) {
	    proc = (Tcl_PackageInitProc *)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);
    }
    return (void *)proc;
}

/*
 *----------------------------------------------------------------------
 *







|









|







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_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,
		(char *)NULL);
    }
    return (void *)proc;
}

/*
 *----------------------------------------------------------------------
 *
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
	    Tcl_Free(ptr);
	}
#endif /* TCL_DYLD_USE_NSMODULE */
    }
    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.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







472
473
474
475
476
477
478




























479
480
481
482
483
484
485
	    Tcl_Free(ptr);
	}
#endif /* TCL_DYLD_USE_NSMODULE */
    }
    Tcl_Free(dyldLoadHandle);
    Tcl_Free(loadHandle);
}





























/*
 *----------------------------------------------------------------------
 *
 * TclpLoadMemoryGetBuffer --
 *
 *	Allocate a buffer that can be used with TclpLoadMemory() below.
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
	return TCL_ERROR;
    }

    /*
     * Extract the module we want from the image of the object file.
     */


    if (!(flags & 1)) 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));
	return TCL_ERROR;
    }

    /*
     * Stash the module reference within the load handle we create and return.
     */








>
|
>
>
|
>








|







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)) {
	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, 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
/*
 * 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.
 *
 * 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 void *		FindSymbol(Tcl_Interp *interp,
			    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
 *	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). */






|









>
>
|
>


|



|







|





|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*
 * tclLoadNext.c --
 *
 *	This procedure provides a version of the TclLoadFile that works with
 *	NeXTs rld_* dynamic loading. This file provided by Pedja Bogdanovich.
 *
 * 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 void *		FindSymbol(Tcl_Interp *interp,
			    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
 *	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

    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
	 */

	Tcl_DString ds;

	native = Tcl_UtfToExternalDString(NULL, fileName, -1, &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->clientData = INT2PTR(1);
    newHandle->findSymbolProcPtr = &FindSymbol;
    newHandle->unloadFileProcPtr = &UnloadFile;
    *loadHandle = newHandle;
    *unloadProcPtr = &UnloadFile;


    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|




|
>
>
>
>

















|



<

>







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

115
116
117
118
119
120
121
122
123

    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.
	 */

	Tcl_DString 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->clientData = INT2PTR(1);
    newHandle->findSymbolProcPtr = &FindSymbol;
    newHandle->unloadFileProcPtr = &UnloadFile;

    *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

static void *
FindSymbol(
    Tcl_Interp *interp,
    Tcl_LoadHandle loadHandle,
    const char *symbol)
{
    Tcl_PackageInitProc *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);
    }
    return proc;
}

/*
 *----------------------------------------------------------------------
 *







|












|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163

static void *
FindSymbol(
    Tcl_Interp *interp,
    Tcl_LoadHandle loadHandle,
    const char *symbol)
{
    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, (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
 *
 * Side effects:
 *	Does nothing.  Can anything be done?
 *
 *----------------------------------------------------------------------
 */

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:
 */







|







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








172
173
174
175
176
177
178
179
180
181
182
183
184
185
186






























187
188
189
190
191
192
193
194
 *
 * Side effects:
 *	Does nothing.  Can anything be done?
 *
 *----------------------------------------------------------------------
 */

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);
}































/*
 * 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
 *			includes: MK6, MK7, AD2, AD3 (from OSF RI)
 *
 *	This approach to things was utter @&^#; thankfully, OSF/1 eventually
 *	supported dlopen().
 *
 *	John Robert LoVerso <[email protected]>
 *
 * Copyright (c) 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 void *		FindSymbol(Tcl_Interp *interp,
			    Tcl_LoadHandle loadHandle, const char* symbol);
static void		UnloadFile(Tcl_LoadHandle handle);

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	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). */







|









>

|



|
|


|







|





|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
 *			includes: MK6, MK7, AD2, AD3 (from OSF RI)
 *
 *	This approach to things was utter @&^#; thankfully, OSF/1 eventually
 *	supported dlopen().
 *
 *	John Robert LoVerso <[email protected]>
 *
 * 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 procedures defined within this file.
 */

static void *		FindSymbol(Tcl_Interp *interp,
			    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
 *	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
    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
     * 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);

    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);
	Tcl_DStringFree(&ds);
    }

    if (lm == LDR_NULL_MODULE) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't load file \"%s\": %s",
		fileName, Tcl_PosixError(interp)));







|





|










|
>
>
>
>
|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
    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
     * important if the cwd is inside a vfs, and we are trying to load using a
     * relative path.
     */

    native = Tcl_FSGetNativePath(pathPtr);
    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;

	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)));
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
    } else {
	pkg++;
    }
    newHandle = (Tcl_LoadHandle)Tcl_Alloc(sizeof(*newHandle));
    newHandle->clientData = pkg;
    newHandle->findSymbolProcPtr = &FindSymbol;
    newHandle->unloadFileProcPtr = &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
 *	interp's result.
 *
 *----------------------------------------------------------------------
 */

static void *
FindSymbol(
    Tcl_Interp *interp,
    Tcl_LoadHandle loadHandle,
    const char *symbol)
{
    void *retval = ldr_lookup_package((char *) loadHandle, symbol);

    if (retval == NULL && interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"cannot find symbol \"%s\"", symbol));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, NULL);
    }
    return retval;
}

/*
 *----------------------------------------------------------------------
 *
 * UnloadFile --
 *







>

|













|











|

|


|

|







133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
    } else {
	pkg++;
    }
    newHandle = (Tcl_LoadHandle)Tcl_Alloc(sizeof(*newHandle));
    newHandle->clientData = pkg;
    newHandle->findSymbolProcPtr = &FindSymbol;
    newHandle->unloadFileProcPtr = &UnloadFile;
    *unloadProcPtr = &UnloadFile;
    *loadHandle = newHandle;

    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
 *	interp's result.
 *
 *----------------------------------------------------------------------
 */

static void *
FindSymbol(
    Tcl_Interp *interp,
    Tcl_LoadHandle loadHandle,
    const char *symbol)
{
    void *proc = ldr_lookup_package((char *) loadHandle, symbol);

    if (proc == NULL && interp != NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"cannot find symbol \"%s\"", symbol));
	Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "LOAD_SYMBOL", symbol, (char *)NULL);
    }
    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
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:
 */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








197
198
199
200
201
202
203






























204
205
206
207
208
209
210
211
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);
}































/*
 * 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
/*
 * 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.
 *
 * 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"







|







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 © 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
 *
 * 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
 *	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). */







|





|







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
 *	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). */
82
83
84
85
86
87
88
89




90
91
92
93
94
95
96
	 * 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);




	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",







|
>
>
>
>







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;

	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
static void*
FindSymbol(
    Tcl_Interp *interp,
    Tcl_LoadHandle loadHandle,
    const char *symbol)
{
    Tcl_DString newName;
    Tcl_PackageInitProc *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) {
	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "_");
	Tcl_DStringAppend(&newName, symbol, -1);
	if (shl_findsym(&handle, Tcl_DStringValue(&newName),
		(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",







|








|


|

|







128
129
130
131
132
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_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) {
	Tcl_DStringInit(&newName);
	TclDStringAppendLiteral(&newName, "_");
	Tcl_DStringAppend(&newName, symbol, TCL_INDEX_NONE);
	if (shl_findsym(&handle, Tcl_DStringValue(&newName),
		(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
				 * 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:
 */







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








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);
}































/*
 * 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
/*
 * 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.
 *
 * 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







|







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 © 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
    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. */
    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.
 */







|







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. */
    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
 * 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;


/*
 * 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 notifier thread signals the notifierCV when it has finished
 * initializing the triggerPipe and right before the notifier thread
 * terminates.
 */

static pthread_cond_t notifierCV = PTHREAD_COND_INITIALIZER;

/*
 * The pollState bits:
 *







>















>
>
>
>
>
>



|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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. 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
#define POLL_DONE	0x2

/*
 * This is the thread ID of the notifier thread that does select.
 */

static Tcl_ThreadId notifierThread;










#endif /* TCL_THREADS */

/*
 * Static routines defined in this file.
 */

#if TCL_THREADS
static TCL_NORETURN void NotifierThreadProc(ClientData 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. */
    int time;			/* Event timestamp. */
    int x;			/* Event location (where meaningful). */
    int y;
    int lPrivate;
} MSG;

typedef struct {







>
>
>
>
>
>
>
>
>
>







|


















|
|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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(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. */
    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
#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 *);
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:
 */


static const wchar_t className[] = L"TclNotifier";
static unsigned int __stdcall	NotifierProc(void *hwnd, unsigned int message,
			    void *wParam, void *lParam);

#ifdef __cplusplus
}
#endif
#endif /* TCL_THREADS && __CYGWIN__ */





#include "tclUnixNotfy.c"

/*
 *----------------------------------------------------------------------
 *
 * 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)
{
    if (tclNotifierHooks.initNotifierProc) {
	return tclNotifierHooks.initNotifierProc();
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

#if TCL_THREADS
	tsdPtr->eventReady = 0;

	/*
	 * Initialize thread specific condition variable for this thread.
	 */

	if (tsdPtr->waitCVinitialized == 0) {
#ifdef __CYGWIN__
	    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;

	    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);
#endif /* __CYGWIN__ */
	    tsdPtr->waitCVinitialized = 1;
	}

	pthread_mutex_lock(&notifierInitMutex);
#if defined(HAVE_PTHREAD_ATFORK)
	/*
	 * 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 (result) {
		Tcl_Panic("Tcl_InitNotifier: pthread_atfork failed");
	    }
	    atForkInit = 1;
	}
#endif /* HAVE_PTHREAD_ATFORK */

	notifierCount++;
	pthread_mutex_unlock(&notifierInitMutex);

#endif /* TCL_THREADS */
	return tsdPtr;
    }

}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
 *
 *	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)
{
    if (tclNotifierHooks.finalizeNotifierProc) {
	tclNotifierHooks.finalizeNotifierProc(clientData);
	return;
    } else {
#if TCL_THREADS
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	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 (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.
	 */

#ifdef __CYGWIN__
	DestroyWindow(tsdPtr->hwnd);
	CloseHandle(tsdPtr->event);
#else /* __CYGWIN__ */
	pthread_cond_destroy(&tsdPtr->waitCV);
#endif /* __CYGWIN__ */
	tsdPtr->waitCVinitialized = 0;

	pthread_mutex_unlock(&notifierInitMutex);
#endif /* TCL_THREADS */
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_CreateFileHandler --
 *
 *	This function registers a file handler with the select notifier.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *
 *----------------------------------------------------------------------
 */

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. */
    ClientData 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;

	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;

	/*
	 * 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;
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_DeleteFileHandler --
 *
 *	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(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    if (tclNotifierHooks.deleteFileHandlerProc) {
	tclNotifierHooks.deleteFileHandlerProc(fd);
	return;
    } else {
	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).
	 */

	for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ;
		prevPtr = filePtr, filePtr = filePtr->nextPtr) {
	    if (filePtr == NULL) {
		return;
	    }
	    if (filePtr->fd == fd) {
		break;
	    }
	}

	/*
	 * 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);
	}

	/*
	 * Find current max fd.
	 */

	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;
	}

	/*
	 * Clean up information in the callback record.
	 */

	if (prevPtr == NULL) {
	    tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
	} else {
	    prevPtr->nextPtr = filePtr->nextPtr;
	}
	Tcl_Free(filePtr);
    }
}

#if defined(__CYGWIN__)

static unsigned int __stdcall
NotifierProc(
    void *hwnd,
    unsigned int message,
    void *wParam,
    void *lParam)







|
|


















>



>




|
>
>
>
|





|












|
|

<
<
<
|


|

|
|
|
>
|

|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|

|
|

|

|
|
|
|

|
|

|
|
|
|
|


|
|
<

<
|
>





|















|
|

<
<
<
<

|

|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
>
>
>
>
>
>
|
|
>
>
|
|
|


|
|
|
|

|

|

<





|













|







|

<
<
<
<
|
|

<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<






|













|



|
<
<
<
|
|
<

|
|
|

<
|
|
|
<
<
<
<
|

|
|
|

|
|
|
|
|
|
|
|
|

|
|
|

|
|

|
|
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
<
|







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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 *);
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"

/*
 *----------------------------------------------------------------------
 *
 * TclpInitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpInitNotifier(void)
{



    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

#if TCL_THREADS
    tsdPtr->eventReady = 0;

    /*
     * Initialize thread specific condition variable for this thread.
     */

    if (tsdPtr->waitCVinitialized == 0) {
#ifdef __CYGWIN__
	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;

	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;
    }

    pthread_mutex_lock(&notifierInitMutex);
#if defined(HAVE_PTHREAD_ATFORK)
    /*
     * 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 (result) {
	    Tcl_Panic("Tcl_InitNotifier: %s", "pthread_atfork failed");
	}
	atForkInit = 1;
    }
#endif /* HAVE_PTHREAD_ATFORK */

    notifierCount++;
    pthread_mutex_unlock(&notifierInitMutex);

#endif /* TCL_THREADS */


    return tsdPtr;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
TclpFinalizeNotifier(
    TCL_UNUSED(void *))
{




#if TCL_THREADS
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    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 (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;

	    /*
	     * 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);
#endif /* __CYGWIN__ */
    tsdPtr->waitCVinitialized = 0;

    pthread_mutex_unlock(&notifierInitMutex);
#endif /* TCL_THREADS */

}

/*
 *----------------------------------------------------------------------
 *
 * TclpCreateFileHandler --
 *
 *	This function registers a file handler with the select notifier.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Creates a new file handler structure.
 *
 *----------------------------------------------------------------------
 */

void
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. */
    void *clientData)	/* Arbitrary data to pass to proc. */
{




    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileHandler *filePtr = LookUpFileHandler(tsdPtr, fd, NULL);







    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.
     */

    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;

    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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
TclpDeleteFileHandler(
    int fd)			/* Stream id for which to remove callback
				 * function. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);



    FileHandler *filePtr, *prevPtr;
    int i;


    /*
     * Find the entry for the given file (and return if there isn't one).
     */


    filePtr = LookUpFileHandler(tsdPtr, fd, &prevPtr);
    if (filePtr == NULL) {
	return;




    }

    /*
     * 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);
    }

    /*
     * Find current max fd.
     */

    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;
    }

    /*
     * Clean up information in the callback record.
     */

    if (prevPtr == NULL) {
	tsdPtr->firstFileHandlerPtr = filePtr->nextPtr;
    } else {
	prevPtr->nextPtr = filePtr->nextPtr;
    }
    Tcl_Free(filePtr);
}


#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
    return 0;
}
#endif /* TCL_THREADS && __CYGWIN__ */

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WaitForEvent --
 *
 *	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(
    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);
#if TCL_THREADS
	int waitForFiles;
#   ifdef __CYGWIN__
	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.
	 */

	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
	 * 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->sec != 0 || timePtr->usec != 0) {
		vTime = *timePtr;
		tclScaleTimeProcPtr(&vTime, tclTimeClientData);
		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.
	     */

	    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");

	pthread_mutex_lock(&notifierMutex);

	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
#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.
	     */

	    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.
	     */

	    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");
	    }
	}

	FD_ZERO(&tsdPtr->readyMasks.readable);
	FD_ZERO(&tsdPtr->readyMasks.writable);
	FD_ZERO(&tsdPtr->readyMasks.exception);

	if (!tsdPtr->eventReady) {
#ifdef __CYGWIN__
	    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);
	    }
#else /* !__CYGWIN__ */
	    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);

		pthread_cond_timedwait(&tsdPtr->waitCV, &notifierMutex, &ptime);
	    } else {
		pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
	    }
#endif /* __CYGWIN__ */
	}
	tsdPtr->eventReady = 0;

#ifdef __CYGWIN__
	while (PeekMessageW(&msg, NULL, 0, 0, 0)) {
	    /*
	     * Retrieve and dispatch the message.
	     */

	    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);
#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 (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);

	/*
	 * 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);
	}
#endif /* TCL_THREADS */

	/*
	 * 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;
	    }

	    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.
	     */

	    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;
	}
#if TCL_THREADS
	pthread_mutex_unlock(&notifierMutex);
#endif /* TCL_THREADS */
	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.

 *
 * 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))
{
    ThreadSpecificData *tsdPtr;
    fd_set readableMask;
    fd_set writableMask;
    fd_set exceptionMask;
    int i;
    int fds[2], receivePipe;
    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");
    }









    receivePipe = fds[0];

    if (TclUnixSetBlockingMode(receivePipe, TCL_MODE_NONBLOCKING) < 0) {
	Tcl_Panic("NotifierThreadProc: %s",
		"could not make receive pipe non blocking");
    }







|















|


<
<
<
|
|
|
|

|

|


|
|
|
|
|

|
|


|
|
|
<
|

|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|

|
|
|

|


|
|
|
|
|
>
|

|

|

|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|

|
|
|

|

|
|

|
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|

|
|
|
|

|
|


|
|
|
|

|

|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|

|
|
|
|
|


|
|
|

|
|
|
|
|
|
|
|
|
|
|
|

|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|

|

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
















|
|
>











|





<
|








>
>
>
>
>
>
>
>







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__ */

/*
 *----------------------------------------------------------------------
 *
 * 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
TclpWaitForEvent(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
{



    FileHandler *filePtr;
    int mask;
    Tcl_Time vTime;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
#if TCL_THREADS
    int waitForFiles;
#   ifdef __CYGWIN__
    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.
     */

    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 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->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.
	 */

	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");

    pthread_mutex_lock(&notifierMutex);

    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
#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.
	 */

	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.
	 */

	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");
	}
    }

    FD_ZERO(&tsdPtr->readyMasks.readable);
    FD_ZERO(&tsdPtr->readyMasks.writable);
    FD_ZERO(&tsdPtr->readyMasks.exception);

    if (!tsdPtr->eventReady) {
#ifdef __CYGWIN__
	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);
	}
#else /* !__CYGWIN__ */
	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);

	    pthread_cond_timedwait(&tsdPtr->waitCV, &notifierMutex, &ptime);
	} else {
	    pthread_cond_wait(&tsdPtr->waitCV, &notifierMutex);
	}
#endif /* __CYGWIN__ */
    }
    tsdPtr->eventReady = 0;

#ifdef __CYGWIN__
    while (PeekMessageW(&msg, NULL, 0, 0, 0)) {
	/*
	 * Retrieve and dispatch the message.
	 */

	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);
#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 (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);

    /*
     * 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);
    }
#endif /* TCL_THREADS */

    /*
     * 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;
	}

	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.
	 */

	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;
    }
#if TCL_THREADS
    pthread_mutex_unlock(&notifierMutex);
#endif /* TCL_THREADS */
    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 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(void *))
{
    ThreadSpecificData *tsdPtr;
    fd_set readableMask;
    fd_set writableMask;
    fd_set exceptionMask;

    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

    /*
     * Install the write end of the pipe into the global variable.
     */

    pthread_mutex_lock(&notifierMutex);
    triggerPipe = fds[1];


    /*
     * Signal any threads that are waiting.
     */

    pthread_cond_broadcast(&notifierCV);
    pthread_mutex_unlock(&notifierMutex);







>







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
	 */

	if (receivePipe >= numFdBits) {
	    numFdBits = receivePipe + 1;
	}
	FD_SET(receivePipe, &readableMask);





















	if (select(numFdBits, &readableMask, &writableMask, &exceptionMask,
		timePtr) == -1) {




	    /*
	     * Try again immediately on an 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) {
		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)) {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>

<
>
>

>
>
>
|
>
>
>
>











|







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);
	ret = select(numFdBits, &readableMask, &writableMask, &exceptionMask,
		timePtr);
	pthread_sigmask(SIG_BLOCK, &allSigMask, NULL);
#endif

	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 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) {
		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
	/*
	 * 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);
	    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 ((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;

    pthread_cond_broadcast(&notifierCV);
    pthread_mutex_unlock(&notifierMutex);

    TclpThreadExit(0);
}
#endif /* TCL_THREADS */

#endif /* (!NOTIFIER_EPOLL && !NOTIFIER_KQUEUE) || !TCL_THREADS */


#endif /* !HAVE_COREFOUNDATION */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|












>
>
>
>
>
>













>








>
>









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 = (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
/*
 * 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.
 *
 * 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 "tclIO.h"	/* To get Channel type declaration. */






|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
 * tclUnixChan.c
 *
 *	Common channel driver for Unix channels based on files, command pipes
 *	and TCP sockets.
 *
 * 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 "tclIO.h"	/* To get Channel type declaration. */
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

#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);		\
    }

/*
 * 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		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);
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,







|











>
>
>





|
|
|







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

#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", (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,
			    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,
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
    "file",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    FileInputProc,		/* Input proc. */
    FileOutputProc,		/* Output proc. */
	NULL,
    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. */







|







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
    "file",			/* Type name. */
    TCL_CHANNEL_VERSION_5,	/* v5 channel */
    NULL,		/* Close proc. */
    FileInputProc,		/* Input proc. */
    FileOutputProc,		/* Output proc. */
	NULL,
    NULL,			/* Set option proc. */
    FileGetOptionProc,		/* 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. */
270
271
272
273
274
275
276

277


278

279
280
281
282
283
284
285
286
287
288
289
    /*
     * 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.
     */


    bytesRead = read(fsPtr->fd, buf, toRead);


    if (bytesRead >= 0) {

	return bytesRead;
    }
    *errorCodePtr = errno;
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * FileOutputProc--
 *







>
|
>
>
|
>
|

<
|







273
274
275
276
277
278
279
280
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
    /*
     * 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);
    } while ((bytesRead < 0) && (errno == EINTR));

    if (bytesRead < 0) {
	*errorCodePtr = errno;
	return -1;
    }

    return bytesRead;
}

/*
 *----------------------------------------------------------------------
 *
 * FileOutputProc--
 *
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
 * Side effects:
 *	Moves the location at which the channel will be accessed in future
 *	operations.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideInt
FileWideSeekProc(
    void *instanceData,	/* File state. */
    Tcl_WideInt 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;

    newLoc = TclOSseek(fsPtr->fd, (Tcl_SeekOffset) offset, mode);

    *errorCodePtr = (newLoc == -1) ? errno : 0;
    return newLoc;
}








|


|





|







442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
 * Side effects:
 *	Moves the location at which the channel will be accessed in future
 *	operations.
 *
 *----------------------------------------------------------------------
 */

static long long
FileWideSeekProc(
    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;
    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
 *
 * Side effects:
 *	Sets up the notifier so that a future event on the channel will
 *	be seen by Tcl.
 *
 *----------------------------------------------------------------------
 */















static void
FileWatchProc(
    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
     * 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);
    } else {
	Tcl_DeleteFileHandler(fsPtr->fd);
    }
}

/*
 *----------------------------------------------------------------------







>
>
>
>
>
>
>
>
>
>
>
>
>
>











|
<
<





|







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
 *
 * 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. */
    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.


     */

    mask &= fsPtr->validMask;
    if (mask) {
	Tcl_CreateFileHandler(fsPtr->fd, mask,
		FileWatchNotifyChannelWrapper, fsPtr->channel);
    } else {
	Tcl_DeleteFileHandler(fsPtr->fd);
    }
}

/*
 *----------------------------------------------------------------------
526
527
528
529
530
531
532










































































































































































533
534
535
536
537
538
539

    if (direction & fsPtr->validMask) {
	*handlePtr = INT2PTR(fsPtr->fd);
	return TCL_OK;
    }
    return TCL_ERROR;
}











































































































































































#ifdef SUPPORTS_TTY
/*
 *----------------------------------------------------------------------
 *
 * TtyModemStatusStr --
 *







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

    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 void
StoreElementInDict(
    Tcl_Obj *dictObj,
    const char *name,
    Tcl_Obj *valueObj)
{
    /*
     * We assume that the dict is being built fresh and that there's never any
     * duplicate keys.
     */

    Tcl_Obj *nameObj = Tcl_NewStringObj(name, -1);
    Tcl_DictObjPut(NULL, dictObj, nameObj, valueObj);
}

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) StoreElementInDict(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 --
 *
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
    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;
    const char **argv;
    struct termios iostate;

    len = strlen(optionName);
    vlen = strlen(value);

    /*







|







777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
    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;
    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
	 */

	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) {
	    /*
	     * Leave all handshake options disabled.
	     */
	} else if (Tcl_UtfNcasecmp(value, "XONXOFF", vlen) == 0) {
	    SET_BITS(iostate.c_iflag, IXON | IXOFF | IXANY);
	} else if (Tcl_UtfNcasecmp(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) {
	    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);
	    }
	    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_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);
	    if ((character > 0xFF) || argv[0][charLen]) {
		goto badXchar;
	    }
	    iostate.c_cc[VSTART] = character;
	    charLen = Tcl_UtfToUniChar(argv[1], &character);
	    if ((character > 0xFF) || argv[1][charLen]) {
		goto badXchar;
	    }
	    iostate.c_cc[VSTOP] = character;
	}
	Tcl_Free(argv);








|



|

|






|








|




















|













|




|







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
	 */

	tcgetattr(fsPtr->fileState.fd, &iostate);
	CLEAR_BITS(iostate.c_iflag, IXON | IXOFF | IXANY);
#ifdef CRTSCTS
	CLEAR_BITS(iostate.c_cflag, CRTSCTS);
#endif /* CRTSCTS */
	if (strncasecmp(value, "NONE", vlen) == 0) {
	    /*
	     * Leave all handshake options disabled.
	     */
	} else if (strncasecmp(value, "XONXOFF", vlen) == 0) {
	    SET_BITS(iostate.c_iflag, IXON | IXOFF | IXANY);
	} 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 (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", (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", (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 = TclUtfToUniChar(argv[0], &character);
	    if ((character > 0xFF) || argv[0][charLen]) {
		goto badXchar;
	    }
	    iostate.c_cc[VSTART] = 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

    /*
     * 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;


	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);
	    }
	    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 (flag) {
		    SET_BITS(control, TIOCM_DTR);
		} else {
		    CLEAR_BITS(control, TIOCM_DTR);
		}
	    } else if (Tcl_UtfNcasecmp(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) {
#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);
		}
		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) {
	    fsPtr->closeMode = CLOSE_DEFAULT;
	} else if (Tcl_UtfNcasecmp(value, "DRAIN", vlen) == 0) {
	    fsPtr->closeMode = CLOSE_DRAIN;
	} else if (Tcl_UtfNcasecmp(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);
	    }
	    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) {
	    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) {
	    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) {
#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) {
	    /*
	     * 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);
	    }
	    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",







|
>










|











|





|





|

















|



















|

|

|







|



















|



|










|










|











|







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

    /*
     * Option -ttycontrol {DTR 1 RTS 0 BREAK 0}
     */

    if ((len > 4) && (strncmp(optionName, "-ttycontrol", len) == 0)) {
#if defined(TIOCMGET) && defined(TIOCMSET)
	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", (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 (strncasecmp(argv[i], "DTR", strlen(argv[i])) == 0) {
		if (flag) {
		    SET_BITS(control, TIOCM_DTR);
		} else {
		    CLEAR_BITS(control, TIOCM_DTR);
		}
	    } 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 (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", (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 (strncasecmp(value, "DEFAULT", vlen) == 0) {
	    fsPtr->closeMode = CLOSE_DEFAULT;
	} else if (strncasecmp(value, "DRAIN", vlen) == 0) {
	    fsPtr->closeMode = CLOSE_DRAIN;
	} 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", (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 (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 (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 (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 (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", (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",
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
	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);
	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_DStringAppendElement(dsPtr, Tcl_DStringValue(&ds));
	TclDStringClear(&ds);

	Tcl_ExternalToUtfDString(NULL, (char *) &iostate.c_cc[VSTOP], 1, &ds);
	Tcl_DStringAppendElement(dsPtr, Tcl_DStringValue(&ds));
	Tcl_DStringFree(&ds);
    }
    if (len == 0) {
	Tcl_DStringEndSublist(dsPtr);
    }








|


















|



|







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
	Tcl_DStringAppendElement(dsPtr, "-mode");
    }
    if (len==0 || (len>2 && strncmp(optionName, "-mode", len)==0)) {
	TtyAttrs tty;

	valid = 1;
	TtyGetAttributes(fsPtr->fileState.fd, &tty);
	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_ExternalToUtfDStringEx(NULL, NULL, (char *) &iostate.c_cc[VSTART], 1, TCL_ENCODING_PROFILE_TCL8, &ds, NULL);
	Tcl_DStringAppendElement(dsPtr, Tcl_DStringValue(&ds));
	TclDStringClear(&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

	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);
	Tcl_DStringAppendElement(dsPtr, buf);
	sprintf(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







|

|







1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252

	valid = 1;
	GETREADQUEUE(fsPtr->fileState.fd, inQueue);
	GETWRITEQUEUE(fsPtr->fileState.fd, outQueue);
	inBuffered = Tcl_InputBuffered(fsPtr->fileState.channel);
	outBuffered = Tcl_OutputBuffered(fsPtr->fileState.channel);

	snprintf(buf, sizeof(buf), "%d", inBuffered+inQueue);
	Tcl_DStringAppendElement(dsPtr, buf);
	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
	    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);
	Tcl_DStringAppendElement(dsPtr, buf);
	sprintf(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");
}

static const struct {int baud; speed_t speed;} speeds[] = {
#ifdef B0
    {0, B0},
#endif
#ifdef B50







|

|








|







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
	    if (interp != NULL) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't read terminal size: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	snprintf(buf, sizeof(buf), "%d", ws.ws_col);
	Tcl_DStringAppendElement(dsPtr, buf);
	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");
}

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
	    &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);
	}
	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.
     */

    if (
#if defined(PAREXT)
        strchr("noems", parity)
#else
        strchr("noe", parity)
#endif /* PAREXT */
                               == NULL) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s parity: should be %s", bad,
#if defined(PAREXT)
		    "n, o, e, m, or s"
#else
		    "n, o, or e"
#endif /* PAREXT */
		    ));
	    Tcl_SetErrorCode(interp, "TCL", "VALUE", "SERIALMODE", 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);
	}
	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);
	}
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*







|










|


















|








|







|







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
	    &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", (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 preprocessor directives in their arguments.
     */

    if (
#if defined(PAREXT)
        strchr("noems", parity)
#else
        strchr("noe", parity)
#endif /* PAREXT */
                               == NULL) {
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "%s parity: should be %s", bad,
#if defined(PAREXT)
		    "n, o, e, m, or s"
#else
		    "n, o, or e"
#endif /* PAREXT */
		    ));
	    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", (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", (char *)NULL);
	}
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
{
    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)) {
    case O_RDONLY:
	channelPermissions = TCL_READABLE;
	break;
    case O_WRONLY:
	channelPermissions = TCL_WRITABLE;
	break;
    case O_RDWR:







|







1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
{
    int fd, channelPermissions;
    TtyState *fsPtr;
    const char *native, *translation;
    char channelName[16 + TCL_INTEGER_SPACE];
    const Tcl_ChannelType *channelTypePtr;

    switch (mode & O_ACCMODE) {
    case O_RDONLY:
	channelPermissions = TCL_READABLE;
	break;
    case O_WRONLY:
	channelPermissions = TCL_WRITABLE;
	break;
    case O_RDWR:
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
    }

    native = (const char *)Tcl_FSGetNativePath(pathPtr);
    if (native == NULL) {
	if (interp != (Tcl_Interp *) NULL) {
	    Tcl_AppendResult(interp, "couldn't open \"",
	    TclGetString(pathPtr), "\": filename is invalid on this platform",
	    NULL);
	}
	return NULL;
    }

#ifdef DJGPP
    SET_BITS(mode, O_BINARY);
#endif







|







1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
    }

    native = (const char *)Tcl_FSGetNativePath(pathPtr);
    if (native == NULL) {
	if (interp != (Tcl_Interp *) NULL) {
	    Tcl_AppendResult(interp, "couldn't open \"",
	    TclGetString(pathPtr), "\": filename is invalid on this platform",
	    (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
	 * 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);
    } else
#endif	/* SUPPORTS_TTY */
    {
	translation = NULL;
	channelTypePtr = &fileChannelType;
	sprintf(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) {







|





|







1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
	 * 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);
	snprintf(channelName, sizeof(channelName), "serial%d", fd);
    } else
#endif	/* SUPPORTS_TTY */
    {
	translation = NULL;
	channelTypePtr = &fileChannelType;
	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
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_MakeFileChannel(
    void *handle,		/* OS level handle. */
    int mode)			/* ORed 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;

    if (mode == 0) {
	return NULL;
    }

#ifdef SUPPORTS_TTY
    if (isatty(fd)) {
	channelTypePtr = &ttyChannelType;
	sprintf(channelName, "serial%d", fd);
    } else
#endif /* SUPPORTS_TTY */
    if (fstat(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);
    }

    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);







|






|








|


|














|







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
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_MakeFileChannel(
    void *handle,		/* OS level handle. */
    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;
    Tcl_StatBuf buf;

    if (mode == 0) {
	return NULL;
    }

#ifdef SUPPORTS_TTY
    if (isatty(fd)) {
	channelTypePtr = &ttyChannelType;
	snprintf(channelName, sizeof(channelName), "serial%d", fd);
    } else
#endif /* SUPPORTS_TTY */
    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;
	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
    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)
		&& (errno == EBADF)) {
	    return NULL;
	}
	fd = 0;
	mode = TCL_READABLE;
	bufMode = "line";
	break;
    case TCL_STDOUT:
	if ((TclOSseek(1, ZERO_OFFSET, 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)
		&& (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;
    }








<




|








|








|












<







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
    int mode = 0;		/* compiler warning (used before set). */
    const char *bufMode = NULL;

    /*
     * Some #def's to make the code a little clearer!
     */


#define ERROR_OFFSET	((Tcl_SeekOffset) -1)

    switch (type) {
    case TCL_STDIN:
	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, 0, SEEK_CUR) == ERROR_OFFSET)
		&& (errno == EBADF)) {
	    return NULL;
	}
	fd = 1;
	mode = TCL_WRITABLE;
	bufMode = "line";
	break;
    case TCL_STDERR:
	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 ERROR_OFFSET

    channel = Tcl_MakeFileChannel(INT2PTR(fd), mode);
    if (channel == NULL) {
	return NULL;
    }

1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
    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);
	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);
	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.







|





|







2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
    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",
		(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",
		(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
	     */

	    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);
		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);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * FileTruncateProc --







|










|







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
	     */

	    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", (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",
	    (char *)NULL);
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
 * FileTruncateProc --
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
 *
 *----------------------------------------------------------------------
 */

static int
FileTruncateProc(
    void *instanceData,
    Tcl_WideInt length)
{
    FileState *fsPtr = (FileState *)instanceData;
    int result;

#ifdef HAVE_TYPE_OFF64_T
    /*
     * We assume this goes with the type for now...







|







2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
 *
 *----------------------------------------------------------------------
 */

static int
FileTruncateProc(
    void *instanceData,
    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
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);
#endif
#ifdef NEED_GR_CLEANER
static void		FreeGrBuf(ClientData dummy);
#endif
#endif /* TCL_THREADS */

/*
 *---------------------------------------------------------------------------
 *
 * TclUnixSetBlockingMode --







|


|







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(void *dummy);
#endif
#ifdef NEED_GR_CLEANER
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
 *
 *---------------------------------------------------------------------------
 */

#ifdef NEED_PW_CLEANER
static void
FreePwBuf(
    TCL_UNUSED(ClientData))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    Tcl_Free(tsdPtr->pbuf);
}
#endif /* NEED_PW_CLEANER */








|







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
 *
 *---------------------------------------------------------------------------
 */

#ifdef NEED_PW_CLEANER
static void
FreePwBuf(
    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
 *
 *---------------------------------------------------------------------------
 */

#ifdef NEED_GR_CLEANER
static void
FreeGrBuf(
    TCL_UNUSED(ClientData))
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    Tcl_Free(tsdPtr->gbuf);
}
#endif /* NEED_GR_CLEANER */








|







513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
 *
 *---------------------------------------------------------------------------
 */

#ifdef NEED_GR_CLEANER
static void
FreeGrBuf(
    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
{
#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;

    return gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
			   sizeof(tsdPtr->hbuf), &h_errno);

#elif defined(HAVE_GETHOSTBYNAME_R_6)
    struct hostent *hePtr = NULL;
    int h_errno, result;

    result = gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
	    sizeof(tsdPtr->hbuf), &hePtr, &h_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;







|


|



|


|







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 local_errno;

    return gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
			   sizeof(tsdPtr->hbuf), &local_errno);

#elif defined(HAVE_GETHOSTBYNAME_R_6)
    struct hostent *hePtr = NULL;
    int local_errno, result;

    result = gethostbyname_r(name, &tsdPtr->hent, tsdPtr->hbuf,
	    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
{
#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;

    return gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
	    sizeof(tsdPtr->hbuf), &h_errno);

#elif defined(HAVE_GETHOSTBYADDR_R_8)
    struct hostent *hePtr;
    int h_errno;

    return (gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
		sizeof(tsdPtr->hbuf), &hePtr, &h_errno) == 0)
	    ? &tsdPtr->hent : NULL;
#else
#define NEED_COPYHOSTENT 1
    struct hostent *hePtr;

    Tcl_MutexLock(&compatLock);
    hePtr = gethostbyaddr(addr, length, type);







|


|



|


|







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 local_errno;

    return gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
	    sizeof(tsdPtr->hbuf), &local_errno);

#elif defined(HAVE_GETHOSTBYADDR_R_8)
    struct hostent *hePtr;
    int local_errno;

    return (gethostbyaddr_r(addr, length, type, &tsdPtr->hent, tsdPtr->hbuf,
		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
#endif /* NEED_COPYGRP */

/*
 *---------------------------------------------------------------------------
 *
 * CopyHostent --
 *
 *      Copies string fields of the hostnent 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







|







730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
#endif /* NEED_COPYGRP */

/*
 *---------------------------------------------------------------------------
 *
 * CopyHostent --
 *
 *      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
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
    __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));
#endif
    status = TCL_OK;



#endif
    return status;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







<






>
|





<

>
>
>











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(__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));
    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));

    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
/*
 * tclUnixEvent.c --
 *
 *	This file implements Unix specific event related routines.
 *
 * Copyright (c) 1997 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.
 */

#include "tclInt.h"
#ifndef HAVE_COREFOUNDATION	/* Darwin/Mac OS X CoreFoundation notifier is





|







1
2
3
4
5
6
7
8
9
10
11
12
13
/*
 * tclUnixEvent.c --
 *
 *	This file implements Unix specific event related routines.
 *
 * 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

	if (vdelay.usec < 0) {
	    vdelay.usec += 1000000;
	    vdelay.sec  -= 1;
	}

	if ((vdelay.sec != 0) || (vdelay.usec != 0)) {
	    tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
	}

	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);
    }
}



#endif /* HAVE_COREFOUNDATION */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|




















>
>








60
61
62
63
64
65
66
67
68
69
70
71
72
73
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)) {
	    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
/*
 * tclUnixFCmd.c
 *
 *	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.
 *
 * 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
 *      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



|



|







|







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
 *	subcommands of the "file" command. All filename arguments should
 *	already be translated to native format.
 *
 * 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 © 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
/*
 * 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__) && \
	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.
 */







<
<
<
|







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(__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
	return TCL_OK;
    }
    if (errno == ENOTEMPTY) {
	errno = EEXIST;
    }

    /*
     * IRIX returns EIO when you attept 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;
    }







|







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 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

    switch ((int) (statBufPtr->st_mode & S_IFMT)) {
#ifndef DJGPP
    case S_IFLNK: {
	char linkBuf[MAXPATHLEN+1];
	int length;

	length = readlink(src, linkBuf, MAXPATHLEN);
							/* INTL: Native. */
	if (length == -1) {
	    return TCL_ERROR;
	}
	linkBuf[length] = '\0';
	if (symlink(linkBuf, dst) < 0) {		/* INTL: Native. */
	    return TCL_ERROR;
	}







|
<







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);	/* 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
    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;

#ifdef DJGPP
#define BINMODE |O_BINARY
#else
#define BINMODE
#endif /* DJGPP */








|







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 */
    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

    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)) {
	    break;
	}
	if ((size_t) write(dstFd, buffer, nread) != nread) {
	    nread = TCL_IO_FAILURE;
	    break;
	}
    }

    Tcl_Free(buffer);
    close(srcFd);
    if ((close(dstFd) != 0) || (nread == TCL_IO_FAILURE)) {
	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.







|


|
|






|







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 == -1) || (nread == 0)) {
	    break;
	}
	if (write(dstFd, buffer, nread) != nread) {
	    nread = -1;
	    break;
	}
    }

    Tcl_Free(buffer);
    close(srcFd);
    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
/*
 *---------------------------------------------------------------------------
 *
 * 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.
 *
 * 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.







|







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 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
{
    Tcl_DString ds;
    Tcl_DString srcString, dstString;
    int ret;
    Tcl_Obj *transPtr;

    transPtr = Tcl_FSGetTranslatedPath(NULL,srcPathPtr);
    Tcl_UtfToExternalDString(NULL,
	    (transPtr != NULL ? TclGetString(transPtr) : NULL),
	    -1, &srcString);
    if (transPtr != NULL) {
	Tcl_DecrRefCount(transPtr);
    }



    transPtr = Tcl_FSGetTranslatedPath(NULL,destPathPtr);
    Tcl_UtfToExternalDString(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);

    if (ret != TCL_OK) {
	*errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
	Tcl_DStringFree(&ds);
	Tcl_IncrRefCount(*errorPtr);
    }
    return ret;
}

/*
 *---------------------------------------------------------------------------







|

|



>
>
>
|
|

|
|
|
|
|
>
>
|
>
>
>
|
|
>
|
|

<
<







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);
    ret = Tcl_UtfToExternalDStringEx(NULL, NULL,
	    (transPtr != NULL ? TclGetString(transPtr) : NULL),
	    -1, 0, &srcString, NULL);
    if (transPtr != NULL) {
	Tcl_DecrRefCount(transPtr);
    }
    if (ret != TCL_OK) {
	*errorPtr = srcPathPtr;
    } else {
	transPtr = Tcl_FSGetTranslatedPath(NULL,destPathPtr);
	ret = Tcl_UtfToExternalDStringEx(NULL, NULL,
	    (transPtr != NULL ? TclGetString(transPtr) : NULL),
	    -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) {


	Tcl_IncrRefCount(*errorPtr);
    }
    return ret;
}

/*
 *---------------------------------------------------------------------------
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
    Tcl_Obj **errorPtr)
{
    Tcl_DString ds;
    Tcl_DString pathString;
    int ret;
    Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);

    Tcl_UtfToExternalDString(NULL,
	    (transPtr != NULL ? TclGetString(transPtr) : NULL),
	    -1, &pathString);
    if (transPtr != NULL) {
	Tcl_DecrRefCount(transPtr);
    }



    ret = DoRemoveDirectory(&pathString, recursive, &ds);
    Tcl_DStringFree(&pathString);






    if (ret != TCL_OK) {
	*errorPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
	Tcl_DStringFree(&ds);
	Tcl_IncrRefCount(*errorPtr);
    }
    return ret;
}

static int
DoRemoveDirectory(







|

|



>
>
>
|
|
>
>
>
|
>
>

<
<







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
    Tcl_Obj **errorPtr)
{
    Tcl_DString ds;
    Tcl_DString pathString;
    int ret;
    Tcl_Obj *transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);

    ret = Tcl_UtfToExternalDStringEx(NULL, NULL,
	    (transPtr != NULL ? TclGetString(transPtr) : NULL),
	    -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);
	/* Note above call only sets ds on error */
	if (ret != TCL_OK) {
	    *errorPtr = Tcl_DStringToObj(&ds);
	}
    }

    if (ret != TCL_OK) {


	Tcl_IncrRefCount(*errorPtr);
    }
    return ret;
}

static int
DoRemoveDirectory(
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
    if (errno == ENOTEMPTY) {
	errno = EEXIST;
    }

    result = TCL_OK;
    if ((errno != EEXIST) || (recursive == 0)) {
	if (errorPtr != NULL) {
	    Tcl_ExternalToUtfDString(NULL, path, -1, errorPtr);
	}
	result = TCL_ERROR;
    }

    /*
     * The directory is nonempty, but the recursive flag has been specified,
     * so we recursively remove all the files in the directory.







|







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_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.
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
	    continue;
	}

	/*
	 * Append name after slash, and recurse on the file.
	 */

	Tcl_DStringAppend(sourcePtr, dirEntPtr->d_name, -1);
	if (targetPtr != NULL) {
	    Tcl_DStringAppend(targetPtr, dirEntPtr->d_name, -1);
	}
	result = TraverseUnixTree(traverseProc, sourcePtr, targetPtr,
		errorPtr, doRewind);
	if (result != TCL_OK) {
	    break;
	} else {
	    numProcessed++;







|

|







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, TCL_INDEX_NONE);
	if (targetPtr != NULL) {
	    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
	}
    }
#endif /* !HAVE_FTS */

  end:
    if (errfile != NULL) {
	if (errorPtr != NULL) {
	    Tcl_ExternalToUtfDString(NULL, errfile, -1, errorPtr);
	}
	result = TCL_ERROR;
    }
#ifdef HAVE_FTS
    if (fts != NULL) {
	fts_close(fts);
    }







|







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_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

    /*
     * 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);
    }
    return TCL_ERROR;
}

/*
 *---------------------------------------------------------------------------
 *







|
|







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_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
    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);
    }
    return TCL_ERROR;
}

/*
 *---------------------------------------------------------------------------
 *







|
|







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_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

    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);
	Tcl_DStringFree(&ds);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|
|







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, 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
    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);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|
|







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, 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
		    "could not read \"%s\": %s",
		    TclGetString(fileName), Tcl_PosixError(interp)));
	}
	return TCL_ERROR;
    }

    *attributePtrPtr = Tcl_ObjPrintf(
	    "%0#5lo", (long) (statBuf.st_mode & 0x00007FFF));
    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
 *
 * SetGroupAttribute --







|







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#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
    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) {
	Tcl_DString ds;
	struct group *groupPtr = NULL;
	const char *string;
	size_t length;

	string = TclGetStringFromObj(attributePtr, &length);

	native = Tcl_UtfToExternalDString(NULL, string, length, &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);
	    }
	    return TCL_ERROR;
	}
	gid = groupPtr->gr_gid;
    }

    native = (const char *)Tcl_FSGetNativePath(fileName);







|



|



|
>
>
>
>










|







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 (TclGetWideIntFromObj(NULL, attributePtr, &gid) != TCL_OK) {
	Tcl_DString ds;
	struct group *groupPtr = NULL;
	const char *string;
	Tcl_Size length;

	string = TclGetStringFromObj(attributePtr, &length);

	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", (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
    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) {
	Tcl_DString ds;
	struct passwd *pwPtr = NULL;
	const char *string;
	size_t length;

	string = TclGetStringFromObj(attributePtr, &length);

	native = Tcl_UtfToExternalDString(NULL, string, length, &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);
	    }
	    return TCL_ERROR;
	}
	uid = pwPtr->pw_uid;
    }

    native = (const char *)Tcl_FSGetNativePath(fileName);







|



|



|
>
>
>
>










|







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 (TclGetWideIntFromObj(NULL, attributePtr, &uid) != TCL_OK) {
	Tcl_DString ds;
	struct passwd *pwPtr = NULL;
	const char *string;
	Tcl_Size length;

	string = TclGetStringFromObj(attributePtr, &length);

	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", (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
    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_DecrRefCount(modeObj);
    }
    if (result == TCL_OK
	    || Tcl_GetWideIntFromObj(NULL, attributePtr, &mode) == TCL_OK) {
	newMode = (mode_t) (mode & 0x00007FFF);
    } else {
	Tcl_StatBuf buf;

	/*
	 * Try the forms "rwxrwxrwx" and "ugo=rwx"
	 *







|
|



|







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, TCL_INDEX_NONE);
	result = TclGetWideIntFromObj(NULL, modeObj, &mode);
	Tcl_DecrRefCount(modeObj);
    }
    if (result == 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
	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);
	    }
	    return TCL_ERROR;
	}
    }

    native = (const char *)Tcl_FSGetNativePath(fileName);
    result = chmod(native, newMode);		/* INTL: Native. */







|







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", (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

    if (strlen(modeStringPtr) != 9) {
	goto chmodStyleCheck;
    }

    newMode = 0;
    for (i = 0; i < 9; i++) {
	switch (*(modeStringPtr+i)) {
	case 'r':
	    if ((i%3) != 0) {
		goto chmodStyleCheck;
	    }
	    newMode |= (1<<(8-i));
	    break;
	case 'w':







|







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]) {
	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
    return TCL_OK;

  chmodStyleCheck:
    /*
     * We now check for an "ugoa+-=rwxst" style permissions string
     */

    for (n = 0 ; *(modeStringPtr+n) != '\0' ; n = n + i) {
	oldMode = *modePtr;
	who = op = what = op_found = who_found = 0;
	for (i = 0 ; *(modeStringPtr+n+i) != '\0' ; i++ ) {
	    if (!who_found) {
		/* who */
		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)) {
		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)) {
	    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) == ',') {
		i++;
		break;
	    }
	}
	switch (op) {
	case 1:
	    *modePtr = oldMode | (who & what);







|


|


|




















|

















|




















|







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 += i) {
	oldMode = *modePtr;
	who = op = what = op_found = who_found = 0;
	for (i = 0 ; modeStringPtr[n + i] != '\0' ; i++ ) {
	    if (!who_found) {
		/* who */
		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]) {
		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]) {
	    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] == ',') {
		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
 * Side effects:
 *
 *---------------------------------------------------------------------------
 */

int
TclpObjNormalizePath(
    TCL_UNUSED(Tcl_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;
    const char *path = TclGetStringFromObj(pathPtr, &pathLen);
    Tcl_DString ds;
    const char *nativePath;
#ifndef NO_REALPATH
    char normPath[MAXPATHLEN];
#endif








|











|







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_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;
    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
	/*
	 * 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 (Realpath(nativePath, normPath) != NULL) {
		if (*nativePath != '/' && *normPath == '/') {
		    /*
		     * realpath transformed a relative path into an
		     * absolute path.  Fall back to the long way.
		     */








|
|
>
>
>
>







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) {
	    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
	if ((cur == '/') && (path != currentPathEndPosition)) {
	    /*
	     * Reached directory separator.
	     */

	    int accessOk;

	    nativePath = Tcl_UtfToExternalDString(NULL, path,
		    currentPathEndPosition - path, &ds);




	    accessOk = access(nativePath, F_OK);
	    Tcl_DStringFree(&ds);

	    if (accessOk != 0) {
		/*
		 * File doesn't exist.
		 */







|
|
>
>
>
>







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;

	    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.
		 */
2046
2047
2048
2049
2050
2051
2052
2053




2054
2055
2056
2057
2058
2059
2060
2061
2062
	     * 'Realpath' transforms an empty string into the normalized pwd,
	     * which is the wrong answer.
	     */

	    return 0;
	}

	nativePath = Tcl_UtfToExternalDString(NULL, path,nextCheckpoint, &ds);




	if (Realpath(nativePath, normPath) != NULL) {
	    size_t newNormLen;

	wholeStringOk:
	    newNormLen = strlen(normPath);
	    if ((newNormLen == Tcl_DStringLength(&ds))
		    && (strcmp(normPath, nativePath) == 0)) {
		/*
		 * The original path is unchanged.







|
>
>
>
>

|







2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
	     * 'Realpath' transforms an empty string into the normalized pwd,
	     * which is the wrong answer.
	     */

	    return 0;
	}

	if (Tcl_UtfToExternalDStringEx(interp, NULL, path,nextCheckpoint, 0, &ds, NULL)) {
	    Tcl_DStringFree(&ds);
	    return -1;
	}
	nativePath = Tcl_DStringValue(&ds);
	if (Realpath(nativePath, normPath) != NULL) {
	    Tcl_Size newNormLen;

	wholeStringOk:
	    newNormLen = strlen(normPath);
	    if ((newNormLen == Tcl_DStringLength(&ds))
		    && (strcmp(normPath, nativePath) == 0)) {
		/*
		 * The original path is unchanged.
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
	    }

	    /*
	     * Free the original path and replace it with the normalized path.
	     */

	    Tcl_DStringFree(&ds);
	    Tcl_ExternalToUtfDString(NULL, normPath, newNormLen, &ds);

	    if (path[nextCheckpoint] != '\0') {
		/*
		 * Append the remaining path components.
		 */

		int normLen = Tcl_DStringLength(&ds);







|







2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
	    }

	    /*
	     * Free the original path and replace it with the normalized path.
	     */

	    Tcl_DStringFree(&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
    Tcl_Obj *basenameObj,
    Tcl_Obj *extensionObj,
    Tcl_Obj *resultingNameObj)
{
    Tcl_DString templ, tmp;
    const char *string;
    int fd;
    size_t length;

    /*
     * We should also check against making more then TMP_MAX of these.
     */

    if (dirObj) {
	string = TclGetStringFromObj(dirObj, &length);
	Tcl_UtfToExternalDString(NULL, string, length, &templ);


    } else {
	Tcl_DStringInit(&templ);
	Tcl_DStringAppend(&templ, DefaultTempDir(), -1); /* INTL: native */
    }

    TclDStringAppendLiteral(&templ, "/");

    if (basenameObj) {
	string = TclGetStringFromObj(basenameObj, &length);
	Tcl_UtfToExternalDString(NULL, string, length, &tmp);



	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);



	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);



	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







|


|




|
>
>


|






|
>
>
>











|
>
>
>















|
|
>
>
>







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;
    Tcl_Size length;

    /*
     * We should also check against making more than TMP_MAX of these.
     */

    if (dirObj) {
	string = TclGetStringFromObj(dirObj, &length);
	if (Tcl_UtfToExternalDStringEx(NULL, NULL, string, length, 0, &templ, NULL) != TCL_OK) {
	    return -1;
	}
    } else {
	Tcl_DStringInit(&templ);
	Tcl_DStringAppend(&templ, DefaultTempDir(), TCL_INDEX_NONE); /* INTL: native */
    }

    TclDStringAppendLiteral(&templ, "/");

    if (basenameObj) {
	string = TclGetStringFromObj(basenameObj, &length);
	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);
	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) {
	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
 * Helper that does *part* of what tempnam() does.
 */

static const char *
DefaultTempDir(void)
{
    const char *dir;
    struct stat buf;

    dir = getenv("TMPDIR");
    if (dir && dir[0] && stat(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) {
	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







|


|






|







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;
    Tcl_StatBuf buf;

    dir = getenv("TMPDIR");
    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 (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
    /*
     * 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);


    } else {
	Tcl_DStringInit(&templ);
	Tcl_DStringAppend(&templ, DefaultTempDir(), -1); /* 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);



	    TclDStringAppendDString(&templ, &tmp);
	    Tcl_DStringFree(&tmp);
	} else {
	    TclDStringAppendLiteral(&templ, DEFAULT_TEMP_DIR_PREFIX);
	}
    } else {
	TclDStringAppendLiteral(&templ, DEFAULT_TEMP_DIR_PREFIX);







|
>
>


|









|
>
>
>







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);
	if (Tcl_UtfToExternalDStringEx(NULL, NULL, string, dirObj->length, 0, &templ, NULL) != TCL_OK) {
	    return NULL;
	}
    } else {
	Tcl_DStringInit(&templ);
	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) {
	    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
	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 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_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s",
	    TclGetString(fileName), Tcl_PosixError(interp)));
}

static WCHAR *
winPathFromObj(
    Tcl_Obj *fileName)







|
|
|
>
>
>
|










|







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.
     */

    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. */
{
    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
/*
 * 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.
 *
 * 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"






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * tclUnixFile.c --
 *
 *	This file contains wrappers around UNIX file handling functions.
 *	These wrappers mask differences between Windows and UNIX.
 *
 * 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"
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
 */

#ifdef __CYGWIN__
void
TclpFindExecutable(
    TCL_UNUSED(const char *) /*argv0*/)
{
    Tcl_Encoding encoding;
    size_t length;
    wchar_t buf[PATH_MAX];
    char name[PATH_MAX * 3 + 1];

    GetModuleFileNameW(NULL, buf, PATH_MAX);
    cygwin_conv_path(3, buf, name, PATH_MAX);
    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);
}
#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;


    if (argv0 == NULL) {
	return;
    }
    Tcl_DStringInit(&buffer);

    name = argv0;







<

|



|





<

|











>







35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
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*/)
{

    size_t length;
    wchar_t buf[PATH_MAX] = L"";
    char name[PATH_MAX * 3 + 1];

    GetModuleFileNameW(NULL, buf, 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;
    }

    TclSetObjNameOfExecutable(
	    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
	TclDStringClear(&buffer);
	if (p != name) {
	    Tcl_DStringAppend(&buffer, name, p - name);
	    if (p[-1] != '/') {
		TclDStringAppendLiteral(&buffer, "/");
	    }
	}
	name = Tcl_DStringAppend(&buffer, argv0, -1);

	/*
	 * 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') {
	    break;
	} else if (*(p+1) == 0) {
	    p = "./";
	} else {
	    p++;
	}
    }

    TclSetObjNameOfExecutable(Tcl_NewObj(), 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_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
	Tcl_DStringFree(&utfName);
	goto done;
    }

    if (TclpGetCwd(NULL, &cwd) == NULL) {

	TclSetObjNameOfExecutable(Tcl_NewObj(), 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_DStringFree(&buffer);
    Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd),
	    Tcl_DStringLength(&cwd), &buffer);
    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_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
    Tcl_DStringFree(&utfName);

  done:
    Tcl_DStringFree(&buffer);
}
#endif








|












|

|





>
|














|

|





>
|














|


|
|








|
|

|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
	TclDStringClear(&buffer);
	if (p != name) {
	    Tcl_DStringAppend(&buffer, name, p - name);
	    if (p[-1] != '/') {
		TclDStringAppendLiteral(&buffer, "/");
	    }
	}
	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] == '\0') {
	    break;
	} else if (p[1] == 0) {
	    p = "./";
	} else {
	    p++;
	}
    }
    TclNewObj(obj);
    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_ExternalToUtfDStringEx(NULL, encoding, name, TCL_INDEX_NONE, TCL_ENCODING_PROFILE_TCL8, &utfName, NULL);
	TclSetObjNameOfExecutable(
		Tcl_NewStringObj(Tcl_DStringValue(&utfName), TCL_INDEX_NONE), encoding);
	Tcl_DStringFree(&utfName);
	goto done;
    }

    if (TclpGetCwd(NULL, &cwd) == NULL) {
	TclNewObj(obj);
	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, TCL_INDEX_NONE);

    Tcl_DStringFree(&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_ExternalToUtfDStringEx(NULL, encoding, Tcl_DStringValue(&buffer), TCL_INDEX_NONE,
	    TCL_ENCODING_PROFILE_TCL8, &utfName, NULL);
    TclSetObjNameOfExecutable(
	    Tcl_NewStringObj(Tcl_DStringValue(&utfName), TCL_INDEX_NONE), encoding);
    Tcl_DStringFree(&utfName);

  done:
    Tcl_DStringFree(&buffer);
}
#endif

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 ((TclOSstat(native, &statBuf) != 0)		/* INTL: Native. */
		|| !S_ISDIR(statBuf.st_mode)) {
	    Tcl_DStringFree(&dsOrig);
	    Tcl_DStringFree(&ds);
	    Tcl_DecrRefCount(fileNamePtr);
	    return TCL_OK;







|
>
>
>
>
>
>







304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
	    }
	}

	/*
	 * Now open the directory for reading and iterate over the contents.
	 */

	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
	    }

	    /*
	     * 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_StringCaseMatch(utfname, pattern, 0)) {
		int typeOk = 1;

		if (types != NULL) {
		    Tcl_DStringSetLength(&ds, nativeDirLen);
		    native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1);
		    matchResult = NativeMatchType(interp, native,
			    entryPtr->d_name, types);
		    typeOk = (matchResult == 1);
		}
		if (typeOk) {
		    Tcl_ListObjAppendElement(interp, resultPtr,
			    TclNewFSPathObj(pathPtr, utfname,







|
>
>
>
>
|





|







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
	    }

	    /*
	     * Now check to see if the file matches, according to both type
	     * and pattern. If so, add the file to the result.
	     */

	    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, 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
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);







    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);

}

/*
 *---------------------------------------------------------------------------
 *
 * TclpObjAccess --
 *







|
>
>
>
>
>
>







|
>
>
|
>







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
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;

    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;
    }
    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
 *	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
 *	codes to determine the cause of the problem.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
TclpGetNativeCwd(
    ClientData clientData)
{
    char buffer[MAXPATHLEN+1];

#ifdef USEGETWD
    if (getwd(buffer) == NULL) {			/* INTL: Native. */
	return NULL;
    }







|








|

|







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
 *	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
 *	codes to determine the cause of the problem.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpGetNativeCwd(
    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
	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);



}

/*
 *---------------------------------------------------------------------------
 *
 * TclpReadlink --
 *







|
>
>
>







801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "error getting working directory name: %s",
		    Tcl_PosixError(interp)));
	}
	return NULL;
    }
    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
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;
    const char *native;
    Tcl_DString ds;

    native = Tcl_UtfToExternalDString(NULL, path, -1, &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
    return NULL;
#endif /* !DJGPP */
}

/*
 *----------------------------------------------------------------------
 *
 * TclpObjStat --
 *







|



|
>
>
>
>







|
|
>
>
|

<







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
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];
    Tcl_Size length;
    const char *native;
    Tcl_DString 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;
    }

    if (Tcl_ExternalToUtfDStringEx(NULL, NULL, link, length, 0, linkPtr, NULL) == TCL_OK) {
	return Tcl_DStringValue(linkPtr);
    }
#endif /* !DJGPP */

    return NULL;

}

/*
 *----------------------------------------------------------------------
 *
 * 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
	/*
	 * 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;

	    /*
	     * 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);




	    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;
	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);
	Tcl_IncrRefCount(linkPtr);
	return linkPtr;
    }
}
#endif /* S_IFLNK */

/*







|












|
>
>
>
>



















|














|
>
>
|







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
	/*
	 * Check symbolic link flag first, since we prefer to create these.
	 */

	if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
	    Tcl_DString ds;
	    Tcl_Obj *transPtr;
	    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);
	    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];
	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;
	}

	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
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclpNativeToNormalized(
    ClientData clientData)
{
    Tcl_DString ds;

    Tcl_ExternalToUtfDString(NULL, (const char *) clientData, -1, &ds);
    return TclDStringToObj(&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
TclNativeCreateNativeRep(
    Tcl_Obj *pathPtr)
{
    char *nativePathPtr;
    const char *str;
    Tcl_DString ds;
    Tcl_Obj *validPathPtr;
    size_t len;

    if (TclFSCwdIsNative()) {
	/*
	 * The cwd is native, which means we can use the translated path
	 * without worrying about normalization (this will also usually be
	 * shorter so the utf-to-external conversion will be somewhat faster).
	 */







|



|
|


















|







|







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
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclpNativeToNormalized(
    void *clientData)
{
    Tcl_DString 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.
 *
 *---------------------------------------------------------------------------
 */

void *
TclNativeCreateNativeRep(
    Tcl_Obj *pathPtr)
{
    char *nativePathPtr;
    const char *str;
    Tcl_DString ds;
    Tcl_Obj *validPathPtr;
    Tcl_Size len;

    if (TclFSCwdIsNative()) {
	/*
	 * The cwd is native, which means we can use the translated path
	 * without worrying about normalization (this will also usually be
	 * shorter so the utf-to-external conversion will be somewhat faster).
	 */
1112
1113
1114
1115
1116
1117
1118
1119




1120
1121
1122
1123
1124
1125
1126
	if (validPathPtr == NULL) {
	    return NULL;
	}
	Tcl_IncrRefCount(validPathPtr);
    }

    str = TclGetStringFromObj(validPathPtr, &len);
    Tcl_UtfToExternalDString(NULL, str, len, &ds);




    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;
    }







|
>
>
>
>







1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
	if (validPathPtr == NULL) {
	    return NULL;
	}
	Tcl_IncrRefCount(validPathPtr);
    }

    str = TclGetStringFromObj(validPathPtr, &len);
    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
 *
 * Side effects:
 *	Memory will be allocated for the copy.
 *
 *---------------------------------------------------------------------------
 */

ClientData
TclNativeDupInternalRep(
    ClientData clientData)
{
    char *copy;
    size_t len;

    if (clientData == NULL) {
	return NULL;
    }







|

|







1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
 *
 * Side effects:
 *	Memory will be allocated for the copy.
 *
 *---------------------------------------------------------------------------
 */

void *
TclNativeDupInternalRep(
    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
    Tcl_Obj *pathPtr,		/* File to modify */
    struct utimbuf *tval)	/* New modification date structure */
{
    return utime((const char *)Tcl_FSGetNativePath(pathPtr), tval);
}

#ifdef __CYGWIN__
























int
TclOSstat(
    const char *name,
    void *cygstat)
{
    struct stat buf;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
    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
/*
 * tclUnixInit.c --
 *
 *	Contains the Unix-specific interpreter initialization functions.
 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 1999 by Scriptics Corporation.
 * All rights reserved.
 */

#include "tclInt.h"
#ifdef HAVE_LANGINFO
#   include <langinfo.h>
#   ifdef __APPLE__





|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * tclUnixInit.c --
 *
 *	Contains the Unix-specific interpreter initialization functions.
 *
 * 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
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
static const char *const processors[NUMPROCESSORS] = {
    "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "amd64", "ia32_on_win64"
};

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;
} SYSTEM_INFO;

typedef struct {
  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








|

|
|



|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|
|
|
|
|
|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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 15
static const char *const processors[NUMPROCESSORS] = {
    "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;
} SYSTEM_INFO;

typedef struct {
    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
#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;

/*
 * 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;

/*
 * 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.
 */







|







|







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 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 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.
 */
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
    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) {
	open("/dev/null", O_RDONLY);
    }
    if (TclOSseek(1, (Tcl_SeekOffset) 0, SEEK_CUR) == -1 && errno == EBADF) {
	open("/dev/null", O_WRONLY);
    }
    if (TclOSseek(2, (Tcl_SeekOffset) 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.







|


|


|







365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
    tclPlatform = TCL_PLATFORM_UNIX;
#endif

    /*
     * Make sure, that the standard FDs exist. [Bug 772288]
     */

    if (TclOSseek(0, 0, SEEK_CUR) == -1 && errno == EBADF) {
	open("/dev/null", O_RDONLY);
    }
    if (TclOSseek(1, 0, SEEK_CUR) == -1 && errno == EBADF) {
	open("/dev/null", O_WRONLY);
    }
    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

    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.
     */

    str = getenv("TCL_LIBRARY");			/* INTL: Native. */
    Tcl_ExternalToUtfDString(NULL, str, -1, &buffer);
    str = Tcl_DStringValue(&buffer);

    if ((str != NULL) && (str[0] != '\0')) {
	Tcl_DString ds;
	int 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);

	/*
	 * If TCL_LIBRARY is set, search there.
	 */

	Tcl_ListObjAppendElement(NULL, pathPtr, Tcl_NewStringObj(str, -1));

	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_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







|



|




|











|





|













|







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

    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 original TCL_LIBRARY path.
     */

    str = getenv("TCL_LIBRARY");			/* INTL: Native. */
    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;
	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.
	 */

	snprintf(installLib, sizeof(installLib), "lib/tcl%s", TCL_VERSION);

	/*
	 * If TCL_LIBRARY is set, search there.
	 */

	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, 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
	    /*
	     * TODO: Pull this value from the TIP 59 table.
	     */

	    str = defaultLibraryDir;
	}
	if (str[0] != '\0') {
	    objPtr = Tcl_NewStringObj(str, -1);
	    Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
	}
    }
    Tcl_DStringFree(&buffer);

    *encodingPtr = Tcl_GetEncoding(NULL, NULL);







    str = TclGetStringFromObj(pathPtr, lengthPtr);

    *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1);
    memcpy(*valuePtr, str, *lengthPtr + 1);
    Tcl_DecrRefCount(pathPtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclpSetInitialEncodings --







|






>
>
>
>
>
>
>
|
>
|
|







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
	    /*
	     * TODO: Pull this value from the TIP 59 table.
	     */

	    str = defaultLibraryDir;
	}
	if (str[0] != '\0') {
	    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, &length);
    *lengthPtr = length;
    *valuePtr = (char *)Tcl_Alloc(length + 1);
    memcpy(*valuePtr, str, length + 1);
    Tcl_DecrRefCount(pathPtr);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclpSetInitialEncodings --
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
	Tcl_DString ds;

	/*
	 * Use a DString so we can modify case.
	 */

	Tcl_DStringInit(&ds);
	encoding = Tcl_DStringAppend(&ds, nl_langinfo(CODESET), -1);
	Tcl_UtfToLower(Tcl_DStringValue(&ds));
	knownEncoding = SearchKnownEncodings(encoding);
	if (knownEncoding != NULL) {
	    Tcl_DStringAppend(bufPtr, knownEncoding, -1);
	} else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
	    Tcl_DStringAppend(bufPtr, encoding, -1);
	}
	Tcl_DStringFree(&ds);
	if (Tcl_DStringLength(bufPtr)) {
	    return Tcl_DStringValue(bufPtr);
	}
    }
#endif /* HAVE_LANGINFO */







|



|

|







638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
	Tcl_DString ds;

	/*
	 * Use a DString so we can modify case.
	 */

	Tcl_DStringInit(&ds);
	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, TCL_INDEX_NONE);
	} else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
	    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

    if (encoding != NULL) {
	const char *p;
	Tcl_DString ds;

	Tcl_DStringInit(&ds);
	p = encoding;
	encoding = Tcl_DStringAppend(&ds, p, -1);
	Tcl_UtfToLower(Tcl_DStringValue(&ds));

	knownEncoding = SearchKnownEncodings(encoding);
	if (knownEncoding != NULL) {
	    Tcl_DStringAppend(bufPtr, knownEncoding, -1);
	} else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
	    Tcl_DStringAppend(bufPtr, encoding, -1);
	}
	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);
	    } else if (NULL != Tcl_GetEncoding(NULL, p)) {
		Tcl_DStringAppend(bufPtr, p, -1);
	    }
	}
	Tcl_DStringFree(&ds);
	if (Tcl_DStringLength(bufPtr)) {
	    return Tcl_DStringValue(bufPtr);
	}
    }
    return Tcl_DStringAppend(bufPtr, TCL_DEFAULT_ENCODING, -1);
}

/*
 *---------------------------------------------------------------------------
 *
 * TclpSetVariables --
 *







|




|

|




















|

|







|







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

    if (encoding != NULL) {
	const char *p;
	Tcl_DString ds;

	Tcl_DStringInit(&ds);
	p = encoding;
	encoding = Tcl_DStringAppend(&ds, p, TCL_INDEX_NONE);
	Tcl_UtfToLower(Tcl_DStringValue(&ds));

	knownEncoding = SearchKnownEncodings(encoding);
	if (knownEncoding != NULL) {
	    Tcl_DStringAppend(bufPtr, knownEncoding, TCL_INDEX_NONE);
	} else if (NULL != Tcl_GetEncoding(NULL, encoding)) {
	    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, TCL_INDEX_NONE);
	    } else if (NULL != Tcl_GetEncoding(NULL, p)) {
		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, 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
    static OSVERSIONINFOW osInfo;
    static int osInfoInitialized = 0;
    char buffer[TCL_INTEGER_SPACE * 2];
#elif !defined(NO_UNAME)
    struct utsname name;
#endif
    int unameOK;

    Tcl_DString ds;

#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_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);

	str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
	if ((str != NULL) && (str[0] != '\0')) {
	    char *p = Tcl_DStringValue(&ds);

	    /*
	     * Convert DYLD_FRAMEWORK_PATH from colon to space separated.
	     */



	    do {
		if (*p == ':') {
		    *p = ' ';

		}
	    } 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_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_GLOBAL_ONLY | TCL_APPEND_VALUE);
		}
		CFRelease(frameworksURL);
	    }
	}
	Tcl_SetVar2(interp, "tcl_pkgPath", NULL, pkgPath,
		TCL_GLOBAL_ONLY | TCL_APPEND_VALUE);
    } else

#endif /* HAVE_COREFOUNDATION */









    {




	Tcl_SetVar2(interp, "tcl_pkgPath", NULL, pkgPath, 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







>
|















>


<
<
<
|


|
|
<
<
<
>
>
|
<
|
<
>
|
<
<
<
<
<













<
<
|
<









<
<
|
<




<
<
<
>

>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
>
>







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
    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_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_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(tclLibPath, -1));
	str = TclGetEnv("DYLD_FRAMEWORK_PATH", &ds);
	if ((str != NULL) && (str[0] != '\0')) {
	    p = Tcl_DStringValue(&ds);
	    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_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_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(tclLibPath, -1));

		}
		CFRelease(frameworksURL);
	    }
	    frameworksURL = CFBundleCopySharedFrameworksURL(bundleRef);
	    if (frameworksURL) {
		if (CFURLGetFileSystemRepresentation(frameworksURL, TRUE,
			(unsigned char*) tclLibPath, MAXPATHLEN) &&
			! TclOSstat(tclLibPath, &statBuf) &&
			S_ISDIR(statBuf.st_mode)) {


		    Tcl_ListObjAppendElement(NULL, pkgListObj, Tcl_NewStringObj(tclLibPath, -1));

		}
		CFRelease(frameworksURL);
	    }
	}



    }
#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;

        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
	    GetVersionExW(&osInfo);
	}
	osInfoInitialized = 1;
    }

    GetSystemInfo(&sysInfo);




    Tcl_SetVar2(interp, "tcl_platform", "os",
	    "Windows NT", TCL_GLOBAL_ONLY);
    sprintf(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;


	unameOK = 1;

	native = Tcl_ExternalToUtfDString(NULL, name.sysname, -1, &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







>
>
>
|
<
|










>



|







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
	    GetVersionExW(&osInfo);
	}
	osInfoInitialized = 1;
    }

    GetSystemInfo(&sysInfo);

    if (osInfo.dwMajorVersion == 10 && osInfo.dwBuildNumber >= 22000) {
	osInfo.dwMajorVersion = 11;
    }
    Tcl_SetVar2(interp, "tcl_platform", "os", "Windows NT", TCL_GLOBAL_ONLY);

    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, 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
     * Copy the username of the real user (according to getuid()) into
     * tcl_platform(user).
     */

    {
	struct passwd *pwEnt = TclpGetPwUid(getuid());
	const char *user;


	if (pwEnt == NULL) {
	    user = "";
	    Tcl_DStringInit(&ds);	/* ensure cleanliness */
	} else {
	    user = Tcl_ExternalToUtfDString(NULL, pwEnt->pw_name, -1, &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.
 *
 * 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
 *	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
TclpFindVariable(
    const char *name,		/* Name of desired environment variable
				 * (native). */
    size_t *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;
    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);
	p2 = name;

	for (; *p2 == *p1; p1++, p2++) {
	    /* NULL loop body. */
	}
	if ((*p1 == '=') && (*p2 == '\0')) {
	    *lengthPtr = p2 - name;







>





|



















|



|









|



|




|





|







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
     * 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, 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 sensitive, on Windows this matches mixed case.
 *
 * Results:
 *	The return value is the index in environ of an entry with the name
 *	"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.
 *
 *----------------------------------------------------------------------
 */

Tcl_Size
TclpFindVariable(
    const char *name,		/* Name of desired environment variable
				 * (native). */
    Tcl_Size *lengthPtr)	/* Used to return length of name (for
				 * successful searches) or number of non-NULL
				 * entries in environ (for unsuccessful
				 * searches). */
{
    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, 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
/*
 * tclUnixNotfy.c --
 *
 *	This file contains subroutines shared by all notifier backend
 *	implementations on *nix platforms.

 *
 * Copyright (c) 1995-1997 Sun Microsystems, Inc.
 * Copyright (c) 2016 Lucio Andrés Illanes Albornoz <[email protected]>

 *
 * 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);
# 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)

{
    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 --
 *
 *	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:




|
>

|
|
>



















|



















>

|
>










>



















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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. It is *included* by the epoll,
 *	kqueue and select notifier implementation files.
 *
 * Copyright © 1995-1997 Sun Microsystems, Inc.
 * Copyright © 2016 Lucio Andrés Illanes Albornoz <[email protected]>
 * 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(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)
{
    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 */

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	kqueue(2) notifier:
 *		write(2)s to the trigger pipe(2) of the specified thread.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_AlertNotifier(
    ClientData clientData)
{
    if (tclNotifierHooks.alertNotifierProc) {
	tclNotifierHooks.alertNotifierProc(clientData);
	return;
    } else {
#ifdef NOTIFIER_SELECT
#if TCL_THREADS
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *)clientData;

	pthread_mutex_lock(&notifierMutex);
	tsdPtr->eventReady = 1;

#   ifdef __CYGWIN__
	PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
#   else
	pthread_cond_broadcast(&tsdPtr->waitCV);
#   endif /* __CYGWIN__ */
	pthread_mutex_unlock(&notifierMutex);


#endif /* TCL_THREADS */
#else /* !NOTIFIER_SELECT */
	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);
	}
#else
	if (write(tsdPtr->triggerPipe[1], "", 1) != 1) {
	    Tcl_Panic("Tcl_AlertNotifier: unable to write to %p->triggerPipe",
		(void *)tsdPtr);
	}
#endif /* NOTIFIER_EPOLL && HAVE_EVENTFD */
#endif /* NOTIFIER_SELECT */
    }


















































}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimer --
 *
 *	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. */
{
    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.
	 */
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ServiceModeHook --
 *
 *	This function is invoked whenever the service mode changes.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_ServiceModeHook(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{
    if (tclNotifierHooks.serviceModeHookProc) {
	tclNotifierHooks.serviceModeHookProc(mode);
	return;
    } else if (mode == TCL_SERVICE_ALL) {
#ifdef NOTIFIER_SELECT
#if TCL_THREADS
	StartNotifierThread("Tcl_ServiceModeHook");
#endif
#endif /* NOTIFIER_SELECT */
    }
}







|
|

<
<
<
<


|

|
|


|

|

|
>
>


|

|
>
|
|
|
|
|

|
|
|
|


|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|















|
|

<
<
<
<
|
|
|
|
|
<



















|



<
<
<
|







100
101
102
103
104
105
106
107
108
109




110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217




218
219
220
221
222

223
224
225
226
227
228
229
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
TclpAlertNotifier(
    void *clientData)
{




#ifdef NOTIFIER_SELECT
#if TCL_THREADS
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData;

    pthread_mutex_lock(&notifierMutex);
    tsdPtr->eventReady = 1;

#   ifdef __CYGWIN__
    PostMessageW(tsdPtr->hwnd, 1024, 0, 0);
#   else
    pthread_cond_broadcast(&tsdPtr->waitCV);
#   endif /* __CYGWIN__ */
    pthread_mutex_unlock(&notifierMutex);
#else
    (void)clientData;
#endif /* TCL_THREADS */
#else /* !NOTIFIER_SELECT */
    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",
		tsdPtr);
    }
#else
    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;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
TclpSetTimer(
    TCL_UNUSED(const Tcl_Time *))		/* Timeout value, may be NULL. */
{




    /*
     * 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
TclpServiceModeHook(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{



    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

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.
         */

        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__ */
}







|
|
|
|
|
|

|

|

|
|

|
|
|
|







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.
	 */

	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
    if (notifierThreadRunning == 1) {
	pthread_cond_destroy(&notifierCV);
    }
    pthread_mutex_init(&notifierInitMutex, NULL);
    pthread_mutex_init(&notifierMutex, NULL);
    pthread_cond_init(&notifierCV, NULL);





    /*
     * 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;




	    /*
	     * 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.
	     */
#ifdef __CYGWIN__
	    DestroyWindow(tsdPtr->hwnd);
	    tsdPtr->hwnd = CreateWindowExW(NULL, className,
		    className, 0, 0, 0, 0, 0, NULL, NULL,
		    TclWinGetTclInstance(), NULL);
	    ResetEvent(tsdPtr->event);







>
>
>
>

















>
>
>
>









|







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 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
	     * The list of registered event handlers at fork time is in
	     * tsdPtr->firstFileHandlerPtr;
	     */
	}
    }

    Tcl_InitNotifier();
}






#endif /* HAVE_PTHREAD_ATFORK */


#endif /* TCL_THREADS */



















#endif /* NOTIFIER_SELECT */





#ifndef HAVE_COREFOUNDATION	/* Darwin/Mac OS X CoreFoundation notifier is





				 * in tclMacOSXNotify.c */
/*
 *----------------------------------------------------------------------
 *
 * TclUnixWaitForFile --
 *
 *	This function waits synchronously for a file to become readable or
 *	writable, with an optional timeout.







|
>
>
>
>
>
>
|
|
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|







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();

#ifdef NOTIFIER_SELECT
    /*
     * Restart the notifier thread for signal handling.
     */

    StartNotifierThread("AtForkChild");
#endif
}
#endif /* HAVE_PTHREAD_ATFORK */
#endif /* TCL_THREADS */
#endif /* NOTIFIER_SELECT */

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	serviced during the execution of this function.
 *
 * Side effects:
 *	Time passes.
 *
 *----------------------------------------------------------------------
 */




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. */







>
>
>







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
	 */

	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:
 */







<

|







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
/*
 * 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.
 *
 * 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 USE_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.






|
|







>
>
>
>
>
>
>
>
>
>
>
|







1
2
3
4
5
6
7
8
9
10
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 © 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 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
 */

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
				 * 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;







|







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. */
    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;
137
138
139
140
141
142
143
144




145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    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);




    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);
	}

	/*
	 * Increment the fd so it can't be 0, which would conflict with the
	 * NULL return for errors.
	 */








|
>
>
>
>











|







148
149
150
151
152
153
154
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;

    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, 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
	return NULL;
    }
    fcntl(fd, F_SETFD, FD_CLOEXEC);
    if (contents != NULL) {
	Tcl_DString dstring;
	char *native;

	native = Tcl_UtfToExternalDString(NULL, contents, -1, &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);
    }
    return MakeFile(fd);
}

/*
 *----------------------------------------------------------------------
 *







|
>
>
>
>
>






|







209
210
211
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;

	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, 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

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. */
    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
				 * 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
				 * 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;






    errPipeIn = NULL;
    errPipeOut = NULL;
    pid = -1;

    /*
     * Create a pipe that the child can use to return error information if







|











|




|











|
>
>
>
>
>







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. */
    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 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 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;
    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
     * 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

    /*
     * 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);
    }
    if (!errorFile) {
        Tcl_GetStdChannel(TCL_STDERR);
    }
#endif





























































    pid = fork();





    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,
		    "%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]);
	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) {



	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







|
>
>
|
>
>
>
|
>
>
|
>












|


|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>















|














|


















>
>
>







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++) {
	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);
    }
    if (!errorFile) {
	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();
	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)))) {
	    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. */
	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
	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);
    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);
    }

    if (errPipeIn) {
	TclpCloseFile(errPipeIn);
    }
    if (errPipeOut) {
	TclpCloseFile(errPipeOut);







|











|







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);
    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);
    }

    if (errPipeIn) {
	TclpCloseFile(errPipeIn);
    }
    if (errPipeOut) {
	TclpCloseFile(errPipeOut);
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746

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. */
    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;







|







833
834
835
836
837
838
839
840
841
842
843
844
845
846
847

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. */
    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;
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792

    /*
     * 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);
    statePtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
	    statePtr, mode);
    return statePtr->channel;
}

/*
 *----------------------------------------------------------------------







|







879
880
881
882
883
884
885
886
887
888
889
890
891
892
893

    /*
     * 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".
     */

    snprintf(channelName, sizeof(channelName), "file%d", channelId);
    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
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;

    /*
     * Punt if the channel is not a command channel.
     */

    chanTypePtr = Tcl_GetChannelType(chan);
    if (chanTypePtr != &pipeChannelType) {







|







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;
    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
	 * routine.
	 */

	if (pipePtr->errorFile) {
	    errChan = Tcl_MakeFileChannel(
		    INT2PTR(GetFd(pipePtr->errorFile)),
		    TCL_READABLE);


	} else {
	    errChan = NULL;
	}
	result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,
		errChan);
    }








>
>







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
 *
 * Side effects:
 *	Sets up the notifier so that a future event on the channel will be
 *	seen by Tcl.
 *
 *----------------------------------------------------------------------
 */















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);
	} 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);
	} else {
	    Tcl_DeleteFileHandler(GetFd(psPtr->outFile));
	}
    }
}

/*







>
>
>
>
>
>
>
>
>
>
>
>
>
>















|








|







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
 *
 * 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,
		    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,
		    PipeWatchNotifyChannelWrapper, psPtr->channel);
	} else {
	    Tcl_DeleteFileHandler(GetFd(psPtr->outFile));
	}
    }
}

/*
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
{
    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);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *







|







1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
{
    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);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PidObjCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    Tcl_Channel chan;
    PipeState *pipePtr;
    int i;
    Tcl_Obj *resultPtr;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
	return TCL_ERROR;
    }








|






|







1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PidObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    Tcl_Channel chan;
    PipeState *pipePtr;
    size_t i;
    Tcl_Obj *resultPtr;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
	return TCL_ERROR;
    }

1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
	 * 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_SetObjResult(interp, resultPtr);
    }
    return TCL_OK;
}

/*







|







1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
	 * 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(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
/*
 * 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.
 *
 *	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.
 *









|







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
 *	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
#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>
#endif
#endif

/*
 *---------------------------------------------------------------------------
 * Parameterize for 64-bit filesystem support.
 *---------------------------------------------------------------------------
 */








<
<
<
<
<
<
|
<
<







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>






#include <dirent.h>



/*
 *---------------------------------------------------------------------------
 * Parameterize for 64-bit filesystem support.
 *---------------------------------------------------------------------------
 */

88
89
90
91
92
93
94


95
96
97
98
99
100
101
#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 SOCKET unsigned int
#   define WSAEWOULDBLOCK 10035
    typedef unsigned short WCHAR;
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wignored-attributes"
#endif







>
>







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
    __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 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 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
#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>

/*







>





<
<
<

>















<
<
<
<


|
|
<
<







<
<
<
<
<







105
106
107
108
109
110
111
112
113
114
115
116
117



118
119
120
121
122
123
124
125
126
127
128
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



#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 HAVE_SYS_TIME_H
#   include <sys/time.h>
#endif
#include <time.h>


#ifndef NO_SYS_WAIT_H
#   include <sys/wait.h>
#endif
#ifdef HAVE_INTTYPES_H
#   include <inttypes.h>
#endif
#include <limits.h>





#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
#   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
 * explicitly. The list of system error messages also isn't generally declared
 * in a header file anywhere.
 *---------------------------------------------------------------------------
 */

#ifdef NO_ERRNO
extern int errno;







|







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
 * 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
#	    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
 * intermittently on Darwin x86_64. rdar://4685553
 *---------------------------------------------------------------------------
 */

#   if defined(__x86_64__) && !defined(FIXED_RDAR_4685553)
#	undef USE_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.







<
|
>
|
|
<
<
|
|
<
|
<
<
<
<
<
<
<







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

    /*
     * 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.


     */
#   undef HAVE_POSIX_SPAWNP

#   undef HAVE_VFORK







#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.

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
/*
 * tclUnixSock.c --
 *
 *	This file contains Unix-specific socket related code.
 *
 * 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.
 */

#include "tclInt.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"

#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.
 */

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
				 * below. */

    int interest;		/* Event types of interest */

    /*
     * Only needed for server sockets
     */

    Tcl_TcpAcceptProc *acceptProc;





|






>













|
















|












<
<
<
|

>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56



57
58
59
60
61
62
63
64
65
66
/*
 * tclUnixSock.c --
 *
 *	This file contains Unix-specific socket related code.
 *
 * 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%" 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.
 */

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 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;
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    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
 * 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
					 * 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







|











<
<
<
<
<
|







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96





97
98
99
100
101
102
103
104
    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 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 */






#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
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 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);

/*
 * 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. */







>
>
>



|













|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
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 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. */
    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. */
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
    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.
 *







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







315
316
317
318
319
320
321























322
323
324
325
326
327
328
    Tcl_Obj *tclObj = TclGetProcessGlobalValue(&hostName);
    return TclGetString(tclObj);
}

/*
 * ----------------------------------------------------------------------
 *























 * TclpFinalizeSockets --
 *
 *	Performs per-thread socket subsystem finalization.
 *
 * Results:
 *	None.
 *
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
/*
 * ----------------------------------------------------------------------
 *
 * 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. 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
 *	    return any error code.
 *
 * Results:
 * 	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.
 *
 *----------------------------------------------------------------------
 */

static int
WaitForConnect(
    TcpState *statePtr,		/* State of the socket. */







|



|




|
|








|







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
/*
 * ----------------------------------------------------------------------
 *
 * 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 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 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 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.
 *
 * Side effects:
 *	Processes socket events off the system queue. May process
 *	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

    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
     */

    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))) {
	*errorCodePtr = EWOULDBLOCK;
	return -1;
    }

    if (errorCodePtr == NULL || GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {







|













|







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

    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.
     */

    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->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)) {
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
    }
    Tcl_DStringAppendElement(dsPtr, nport);
}

/*
 *----------------------------------------------------------------------
 *

















































































 * TcpGetOptionProc --
 *
 *	Computes an option value for a TCP socket based channel, or a list of
 *	all options and their values.
 *
 *	Note: This code is based on code contributed by John Haxby.
 *
 * Results:
 *	A standard Tcl result. The value of the specified option or a list of
 *	all options and their values is returned in the supplied DString. Sets
 *	Error message if needed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TcpGetOptionProc(
    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);


        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;

            getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &err,
                    &optlen);
            errno = err;
        }
        if (errno != 0) {
	    Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(errno), -1);
        }
	return TCL_OK;
    }

    if ((len > 1) && (optionName[1] == 'c') &&
	    (strncmp(optionName, "-connecting", len) == 0)) {

        Tcl_DStringAppend(dsPtr,
                GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT) ? "1" : "0", -1);
        return TCL_OK;
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (strncmp(optionName, "-peername", len) == 0))) {
        address peername;
        socklen_t size = sizeof(peername);


	if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) {
	    /*
	     * In async connect output an empty string
	     */

	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




















|










<
<








>

















|






>
|
|








>







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
    }
    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
 *	all options and their values.
 *
 *	Note: This code is based on code contributed by John Haxby.
 *
 * Results:
 *	A standard Tcl result. The value of the specified option or a list of
 *	all options and their values is returned in the supplied DString. Sets
 *	Error message if needed.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TcpGetOptionProc(
    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;



    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.
             */

            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), 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", 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);

	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");
930
931
932
933
934
935
936
937
938
939
940

941
942
943
944
945
946
947
	    }
	}
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 's') &&
	    (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_CONNECT)) {
	    /*
	     * In async connect output an empty string







|
|


>







986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
	    }
	}
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 's') &&
	    (strncmp(optionName, "-sockname", len) == 0))) {
	TcpFdList *fds;
	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
966
967
968
969
970
971
972
973















974

























975
976
977
978
979
980
981
982
983
            if (interp) {
                Tcl_SetObjResult(interp, Tcl_ObjPrintf(
                        "can't get sockname: %s", Tcl_PosixError(interp)));
            }
	    return TCL_ERROR;
	}
    }
















    if (len > 0) {

























	return Tcl_BadChannelOption(interp, optionName,
                "connecting peername sockname");
    }

    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







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
            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) {
	    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 keepalive nodelay peername sockname");
    }

    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
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

	/*
	 * 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
	 * 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);
    } else {
        Tcl_DeleteFileHandler(statePtr->fds.fd);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * TcpGetHandleProc --







|













|
|

|







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

	/*
	 * 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
	 * 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,
		WrapNotify, statePtr);
    } else {
	Tcl_DeleteFileHandler(statePtr->fds.fd);
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * TcpGetHandleProc --
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
    }

    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) {

	    /*
	     * No need to try combinations of local and remote addresses of
	     * different families.
	     */

	    if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) {
		continue;







<







1318
1319
1320
1321
1322
1323
1324

1325
1326
1327
1328
1329
1330
1331
    }

    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) {

	    /*
	     * No need to try combinations of local and remote addresses of
	     * different families.
	     */

	    if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) {
		continue;
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
        TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);

        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().
         */








|







1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
        TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking);

        if (error != 0) {
            SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);
        }

        /*
         * 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().
         */

1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
     */

    if (TcpConnect(interp, statePtr) != TCL_OK) {
        TcpCloseProc(statePtr, NULL);
        return NULL;
    }

    sprintf(channelName, SOCK_TEMPLATE, (long) statePtr);

    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
            statePtr, TCL_READABLE | TCL_WRITABLE);
    if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
	Tcl_CloseEx(NULL, statePtr->channel, 0);
	return NULL;







|







1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
     */

    if (TcpConnect(interp, statePtr) != TCL_OK) {
        TcpCloseProc(statePtr, NULL);
        return NULL;
    }

    snprintf(channelName, sizeof(channelName), SOCK_TEMPLATE, PTR2INT(statePtr));

    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
            statePtr, TCL_READABLE | TCL_WRITABLE);
    if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation",
	    "auto crlf") == TCL_ERROR) {
	Tcl_CloseEx(NULL, statePtr->channel, 0);
	return NULL;
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
 *
 *----------------------------------------------------------------------
 */

void *
TclpMakeTcpClientChannelMode(
    void *sock,		/* The socket to wrap up into a channel. */
    int mode)			/* ORed 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);

    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;







|










|







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
 *
 *----------------------------------------------------------------------
 */

void *
TclpMakeTcpClientChannelMode(
    void *sock,		/* The socket to wrap up into a channel. */
    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;

    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

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. */

    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 */







>







1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656

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 */
1711
1712
1713
1714
1715
1716
1717



1718
1719
1720
1721
1722
1723
1724
1725
             * addresses.
             */

            if (getsockname(sock, &sockname.sa, &namelen) >= 0) {
                chosenport = ntohs(sockname.sa4.sin_port);
            }
        }



        status = listen(sock, SOMAXCONN);
        if (status < 0) {
	    if (howfar < LISTEN) {
		howfar = LISTEN;
		my_errno = errno;
	    }
            close(sock);
            sock = -1;







>
>
>
|







1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
             * addresses.
             */

            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;
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
             * 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;







|







1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
             * Allocate a new TcpState for this socket.
             */

            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;
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
    }
    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);

	if (errorMsg == NULL) {
            errno = my_errno;
            Tcl_AppendToObj(errorObj, Tcl_PosixError(interp), -1);
        } else {
	    Tcl_AppendToObj(errorObj, errorMsg, -1);
	}
        Tcl_SetObjResult(interp, errorObj);
    }
    if (sock != -1) {
	close(sock);
    }
    return NULL;







|



|

|







1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
    }
    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: ", TCL_INDEX_NONE);

	if (errorMsg == NULL) {
            errno = my_errno;
            Tcl_AppendToObj(errorObj, Tcl_PosixError(interp), TCL_INDEX_NONE);
        } else {
	    Tcl_AppendToObj(errorObj, errorMsg, TCL_INDEX_NONE);
	}
        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
    (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);
    newSockState->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    newSockState, TCL_READABLE | TCL_WRITABLE);

    Tcl_SetChannelOption(NULL, newSockState->channel, "-translation",
	    "auto crlf");

    if (fds->statePtr->acceptProc != NULL) {







|







1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
    (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;

    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) {

Changes to unix/tclUnixTest.c.

1
2
3
4
5
6
7
8
9
10
11
12


13
14
15
16
17
18
19
/*
 * tclUnixTest.c --
 *
 *	Contains platform specific test commands for the Unix platform.
 *
 * Copyright (c) 1996-1997 Sun Microsystems, Inc.
 * Copyright (c) 1998 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 USE_TCL_STUBS
#   define USE_TCL_STUBS
#endif
#include "tclInt.h"

/*
 * The headers are needed for the testalarm command that verifies the use of





|
|





>
>







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 © 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
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);

/*
 *----------------------------------------------------------------------
 *
 * TclplatformtestInit --
 *
 *	Defines commands that test platform specific functionality for Unix







|







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);

/*
 *----------------------------------------------------------------------
 *
 * 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
    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);
    Tcl_CreateObjCommand(interp, "testalarm", TestalarmCmd,
	    NULL, NULL);
    Tcl_CreateObjCommand(interp, "testgotsig", TestgotsigCmd,
	    NULL, NULL);
    return TCL_OK;
}








|







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);
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestfilehandlerCmd(
    TCL_UNUSED(ClientData),
    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;







|







127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestfilehandlerCmd(
    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
	    testPipes[i].readFile = NULL;
	}
	initialized = 1;
    }

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option ...");
        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);
	    return TCL_ERROR;
	}
	pipePtr = &testPipes[i];
    }

    if (strcmp(Tcl_GetString(objv[1]), "close") == 0) {
	for (i = 0; i < MAX_PIPES; i++) {







|







|







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;
    }
    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], (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
    } 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);
    } 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);
		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);
	    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);
	    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);
	    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) {
	    /* 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);
    } 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);
	    return TCL_ERROR;
	}
	if (strcmp(Tcl_GetString(objv[3]), "readable") == 0) {
	    mask = TCL_READABLE;
	    file = pipePtr->readFile;
	} else {
	    mask = TCL_WRITABLE;







|
|








|







|















|











|








|

|




















|








|







188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
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;
	}
	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), (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",
		    (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]), "\"", (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]), "\"", (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) {
	    /* 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, (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", (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
	    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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static void
TestFileHandlerProc(
    ClientData 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++;







|







|







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", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

static void
TestFileHandlerProc(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestfilewaitCmd(
    TCL_UNUSED(ClientData),
    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;

    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);
	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);
	return TCL_ERROR;
    }
    fd = PTR2INT(data);
    if (Tcl_GetIntFromObj(interp, objv[3], &timeout) != TCL_OK) {
	return TCL_ERROR;
    }
    result = TclUnixWaitForFile(fd, mask, timeout);







|







|

















|




|
|







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(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;
    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", (char *)NULL);
	return TCL_ERROR;
    }
    if (Tcl_GetChannelHandle(channel,
	    (mask & TCL_READABLE) ? TCL_READABLE : TCL_WRITABLE,
	    (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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestfindexecutableCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)	/* Argument strings. */
{
    Tcl_Obj *saveName;

    if (objc != 2) {







|







409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestfindexecutableCmd(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestforkCmd(
    TCL_UNUSED(ClientData),
    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;
    }
    pid = fork();
    if (pid == -1) {
        Tcl_AppendResult(interp,
                "Cannot fork", 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));







|







|
|



|
|
|







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(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;
    }
    pid = fork();
    if (pid == -1) {
	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
 *	Sets up an signal and async handlers.
 *
 *----------------------------------------------------------------------
 */

static int
TestalarmCmd(
    TCL_UNUSED(ClientData),
    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));
    action.sa_flags = SA_RESTART;

    if (sigaction(SIGALRM, &action, NULL) < 0) {
	Tcl_AppendResult(interp, "sigaction: ", Tcl_PosixError(interp), NULL);
	return TCL_ERROR;
    }
    (void) alarm(sec);
    return TCL_OK;
#else

    Tcl_AppendResult(interp,
	    "warning: sigaction SA_RESTART not support on this platform",
	    NULL);
    return TCL_ERROR;
#endif
}

/*
 *----------------------------------------------------------------------
 *







|


















|



|








|







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
 *	Sets up an signal and async handlers.
 *
 *----------------------------------------------------------------------
 */

static int
TestalarmCmd(
    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));
    action.sa_flags = SA_RESTART;

    if (sigaction(SIGALRM, &action, NULL) < 0) {
	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",
	    (char *)NULL);
    return TCL_ERROR;
#endif
}

/*
 *----------------------------------------------------------------------
 *
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
 *	Resets the value of gotsig back to '0'.
 *
 *----------------------------------------------------------------------
 */

static int
TestgotsigCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *))
{
    Tcl_AppendResult(interp, gotsig, 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
 *	file is made read-write.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Changes permissions of specified files.
 *
 *---------------------------------------------------------------------------
 */

static int
TestchmodCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,			/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const *objv)		/* Argument strings. */
{
    int i, mode;

    if (objc < 2) {







|




|











|













|







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
 *	Resets the value of gotsig back to '0'.
 *
 *----------------------------------------------------------------------
 */

static int
TestgotsigCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,		/* Current interpreter. */
    TCL_UNUSED(int) /*objc*/,
    TCL_UNUSED(Tcl_Obj *const *))
{
    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.  Otherwise, the
 *	file is made read-write.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	Changes permissions of specified files.
 *
 *---------------------------------------------------------------------------
 */

static int
TestchmodCmd(
    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

	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);
	    return TCL_ERROR;
	}
	Tcl_DStringFree(&buffer);
    }
    return TCL_OK;
}








|







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),
		    (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
/*
 * 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
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"






|
|
|







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 © 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
 *----------------------------------------------------------------------
 */

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 */
    int flags)			/* Flags controlling behaviour of the new
				 * thread. */
{
#if TCL_THREADS
    pthread_attr_t attr;
    pthread_t theThread;
    int result;







|
|







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 */
    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
	 * 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);
	}
#endif /* TCL_THREAD_STACK_MIN */
    }
#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */

    if (!(flags & TCL_THREAD_JOINABLE)) {
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);







|







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);
	}
#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
    } else {
	*idPtr = (Tcl_ThreadId)theThread;
	result = TCL_OK;
    }
    pthread_attr_destroy(&attr);
    return result;
#else





    return TCL_ERROR;
#endif /* TCL_THREADS */
}

/*
 *----------------------------------------------------------------------
 *







>
>
>
>
>







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

    result = pthread_join((pthread_t) threadId, (void**) retcodePtr);
    if (state) {
	*state = (int) retcode;
    }
    return (result == 0) ? TCL_OK : TCL_ERROR;
#else



    return TCL_ERROR;
#endif
}

/*
 *----------------------------------------------------------------------
 *







>
>
>







307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323

    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
}

/*
 *----------------------------------------------------------------------
 *

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
/*
 * tclUnixTime.c --
 *
 *	Contains Unix specific versions of Tcl functions that obtain time
 *	values from the operating system.
 *
 * 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.
 */

#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);
static void		NativeGetTime(Tcl_Time *timebuf,
			    ClientData clientData);

/*
 * TIP #233 (Virtualized Time): Data for the time hooks, if any.
 */

Tcl_GetTimeProc *tclGetTimeProcPtr = NativeGetTime;
Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime;
void *tclTimeClientData = NULL;


















/*
 *----------------------------------------------------------------------
 *
 * 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
TclpGetSeconds(void)
{
    return 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
TclpGetMicroseconds(void)
{
    Tcl_Time time;

    tclGetTimeProcPtr(&time, tclTimeClientData);
    return ((Tcl_WideInt)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
 *	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
TclpGetClicks(void)
{
	Tcl_WideUInt now;

#ifdef NO_GETTOD
    if (tclGetTimeProcPtr != NativeGetTime) {
	Tcl_Time time;

	tclGetTimeProcPtr(&time, tclTimeClientData);

	now = (Tcl_WideUInt)time.sec*1000000 + time.usec;
    } else {
	/*
	 * A semi-NativeGetTime, specialized to clicks.
	 */
	struct tms dummy;

	now = (Tcl_WideUInt) times(&dummy);
    }
#else
    Tcl_Time time;

    tclGetTimeProcPtr(&time, tclTimeClientData);

    now = (Tcl_WideUInt)time.sec*1000000 + time.usec;
#endif

    return now;
}
#ifdef TCL_WIDE_CLICKS

/*
 *----------------------------------------------------------------------






|















|

|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















|


|



















|




|
|








|












|


|


|


|
>
|






|

|


|
>
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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 © 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,
			    void *clientData);
static void		NativeGetTime(Tcl_Time *timebuf,
			    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.
 *
 *----------------------------------------------------------------------
 */

unsigned long long
TclpGetSeconds(void)
{
    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.
 *
 *----------------------------------------------------------------------
 */

long long
TclpGetMicroseconds(void)
{
    Tcl_Time time;

    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 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.
 *
 *----------------------------------------------------------------------
 */

unsigned long long
TclpGetClicks(void)
{
    unsigned long long now;

#ifdef NO_GETTOD
    if (!IsTimeNative()) {
	Tcl_Time time;

	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 = (unsigned long long) times(&dummy);
    }
#else /* !NO_GETTOD */
    Tcl_Time time;

    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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
TclpGetWideClicks(void)
{
    Tcl_WideInt now;

    if (tclGetTimeProcPtr != NativeGetTime) {
	Tcl_Time time;

	tclGetTimeProcPtr(&time, tclTimeClientData);
	now = ((Tcl_WideInt)time.sec)*1000000 + time.usec;
    } else {
#ifdef MAC_OSX_TCL
	now = (Tcl_WideInt) (mach_absolute_time() & INT64_MAX);
#else
#error Wide high-resolution clicks not implemented on this platform
#endif
    }

    return now;
}

/*
 *----------------------------------------------------------------------







|


|

|


|
|


|


|







164
165
166
167
168
169
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.
 *
 *----------------------------------------------------------------------
 */

long long
TclpGetWideClicks(void)
{
    long long now;

    if (!IsTimeNative()) {
	Tcl_Time time;

	GetTime(&time);
	now = ((long long) time.sec)*1000000 + time.usec;
    } else {
#ifdef MAC_OSX_TCL
	now = (long long) (mach_absolute_time() & INT64_MAX);
#else
#error Wide high-resolution clicks not implemented on this platform
#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
 *	None.
 *
 *----------------------------------------------------------------------
 */

double
TclpWideClicksToNanoseconds(
    Tcl_WideInt clicks)
{
    double nsec;

    if (tclGetTimeProcPtr != NativeGetTime) {
	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
    }

    return nsec;
}

/*
 *----------------------------------------------------------------------







|



|

















|







204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
 *	None.
 *
 *----------------------------------------------------------------------
 */

double
TclpWideClicksToNanoseconds(
    long long clicks)
{
    double nsec;

    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 /* MAC_OSX_TCL */
    }

    return nsec;
}

/*
 *----------------------------------------------------------------------
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258

259
260
261
262
263
264
265
266
267
268
 *
 *----------------------------------------------------------------------
 */

double
TclpWideClickInMicrosec(void)
{
    if (tclGetTimeProcPtr != NativeGetTime) {
	return 1.0;
    } else {
#ifdef MAC_OSX_TCL
	static int initialized = 0;
	static double scale = 0.0;

	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;
	    initialized = 1;
	    return scale;
	}

#else
#error Wide high-resolution clicks not implemented on this platform
#endif
    }
}
#endif /* TCL_WIDE_CLICKS */

/*
 *----------------------------------------------------------------------
 *







|






|
<
<




|

<

>


|







253
254
255
256
257
258
259
260
261
262
263
264
265
266
267


268
269
270
271
272
273

274
275
276
277
278
279
280
281
282
283
284
285
 *
 *----------------------------------------------------------------------
 */

double
TclpWideClickInMicrosec(void)
{
    if (!IsTimeNative()) {
	return 1.0;
    } else {
#ifdef MAC_OSX_TCL
	static int initialized = 0;
	static double scale = 0.0;

	if (!initialized) {


	    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;
	    initialized = 1;

	}
	return scale;
#else
#error Wide high-resolution clicks not implemented on this platform
#endif /* MAC_OSX_TCL */
    }
}
#endif /* TCL_WIDE_CLICKS */

/*
 *----------------------------------------------------------------------
 *
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
 *----------------------------------------------------------------------
 */

void
Tcl_GetTime(
    Tcl_Time *timePtr)		/* Location to store time information. */
{
    tclGetTimeProcPtr(timePtr, tclTimeClientData);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimeProc --
 *







|







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. */
{
    GetTime(timePtr);
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimeProc --
 *
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    ClientData clientData)
{
    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;
}

/*







|







324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    void *clientData)
{
    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;
}

/*
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
 *----------------------------------------------------------------------
 */

void
Tcl_QueryTimeProc(
    Tcl_GetTimeProc **getProc,
    Tcl_ScaleTimeProc **scaleProc,
    ClientData *clientData)
{
    if (getProc) {
	*getProc = tclGetTimeProcPtr;
    }
    if (scaleProc) {
	*scaleProc = tclScaleTimeProcPtr;
    }







|







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
 *----------------------------------------------------------------------
 */

void
Tcl_QueryTimeProc(
    Tcl_GetTimeProc **getProc,
    Tcl_ScaleTimeProc **scaleProc,
    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
 *
 *----------------------------------------------------------------------
 */

static void
NativeScaleTime(
    TCL_UNUSED(Tcl_Time *),
    TCL_UNUSED(ClientData))
{
    /* Native scale is 1:1. Nothing is done */
}

/*
 *----------------------------------------------------------------------
 *







|







384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
 *
 *----------------------------------------------------------------------
 */

static void
NativeScaleTime(
    TCL_UNUSED(Tcl_Time *),
    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
 *
 *----------------------------------------------------------------------
 */

static void
NativeGetTime(
    Tcl_Time *timePtr,
    TCL_UNUSED(ClientData))
{
    struct timeval tv;

    (void) gettimeofday(&tv, NULL);
    timePtr->sec = tv.tv_sec;
    timePtr->usec = tv.tv_usec;
}







|







409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
 *
 *----------------------------------------------------------------------
 */

static void
NativeGetTime(
    Tcl_Time *timePtr,
    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
/*
 * tclXtNotify.c --
 *
 *	This file contains the notifier driver implementation for the Xt
 *	intrinsics.
 *
 * Copyright (c) 1997 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.
 */

#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
 * 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. */
    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.
 */






|












|















|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 © 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
 * 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. */
    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
/*
 * 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		TimerProc(XtPointer clientData, XtIntervalId *id);
static void		CreateFileHandler(int fd, int mask,
			    Tcl_FileProc *proc, ClientData 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 XtAppContext TclSetAppContext(XtAppContext ctx);

/*
 *----------------------------------------------------------------------
 *
 * TclSetAppContext --
 *







|


|








|







75
76
77
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(void *clientData);
static void		TimerProc(XtPointer clientData, XtIntervalId *id);
static void		CreateFileHandler(int fd, int mask,
			    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 XtAppContext TclSetAppContext(XtAppContext ctx);

/*
 *----------------------------------------------------------------------
 *
 * TclSetAppContext --
 *
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");
	}
    } else {
	/*
	 * If we get here we have not yet gotten a context, so either create
	 * one or use the one supplied by our caller.
	 */








|







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");
	}
    } 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
 *
 *----------------------------------------------------------------------
 */

void
InitNotifier(void)
{
    Tcl_NotifierProcs np;







    /*
     * 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 --







|
>
>
>
>
>
>











<
<
<
<
<
<
<
<








<







177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
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)
{
    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;
    }









    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;

    Tcl_CreateExitHandler(NotifierExitHandler, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * NotifierExitHandler --
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
 *	Destroys the notifier window.
 *
 *----------------------------------------------------------------------
 */

static void
NotifierExitHandler(
    TCL_UNUSED(ClientData))
{
    if (notifier.currentTimeout != 0) {
	XtRemoveTimeOut(notifier.currentTimeout);
    }
    for (; notifier.firstFileHandlerPtr != NULL; ) {
	Tcl_DeleteFileHandler(notifier.firstFileHandlerPtr->fd);
    }







|







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
 *	Destroys the notifier window.
 *
 *----------------------------------------------------------------------
 */

static void
NotifierExitHandler(
    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
    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. */
{
    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->fd = fd;
	filePtr->read = 0;
	filePtr->write = 0;
	filePtr->except = 0;
	filePtr->readyMask = 0;
	filePtr->mask = 0;
	filePtr->nextPtr = notifier.firstFileHandlerPtr;







|
















|







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. */
    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->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

static void
FileProc(
    XtPointer clientData,
    int *fd,
    XtInputId *id)
{
    FileHandler *filePtr = (FileHandler *)clientData;
    FileHandlerEvent *fileEvPtr;
    int mask = 0;

    /*
     * Determine which event happened.
     */








|







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;
    FileHandlerEvent *fileEvPtr;
    int mask = 0;

    /*
     * Determine which event happened.
     */

521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
    }

    /*
     * This is an interesting event, so put it onto the event queue.
     */

    filePtr->readyMask |= mask;
    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.
     */







|







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->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
/*
 * tclXtTest.c --
 *
 *	Contains commands for Xt notifier specific tests on Unix.
 *
 * Copyright (c) 1997 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.
 */

#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 XtAppContext	TclSetAppContext(XtAppContext ctx);

/*
 *----------------------------------------------------------------------
 *
 * Tclxttest_Init --
 *





|












<





|







1
2
3
4
5
6
7
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 © 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;


/*
 * Functions defined in tclXtNotify.c for use by users of the Xt Notifier:
 */

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
 *
 * Side effects:
 *	Depends on the startup script.
 *
 *----------------------------------------------------------------------
 */

int
Tclxttest_Init(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }
    XtToolkitInitialize();







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 *
 * Side effects:
 *	Depends on the startup script.
 *
 *----------------------------------------------------------------------
 */

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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TesteventloopCmd(
    TCL_UNUSED(ClientData),
    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. */







|







73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TesteventloopCmd(
    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
	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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * tab-width: 8
 * End:
 */







|













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", (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
# 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







|
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.3

Changes to win/Makefile.in.

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
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

# 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)

GENERIC_DIR		= $(TOP_DIR)/generic
WIN_DIR			= $(TOP_DIR)/win
COMPAT_DIR		= $(TOP_DIR)/compat
PKGS_DIR		= $(TOP_DIR)/pkgs
ZLIB_DIR		= $(COMPAT_DIR)/zlib
MINIZIP_DIR		= $(ZLIB_DIR)/contrib/minizip
TOMMATH_DIR		= $(TOP_DIR)/libtommath







|















>







78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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

# 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
ZLIB_DIR		= $(COMPAT_DIR)/zlib
MINIZIP_DIR		= $(ZLIB_DIR)/contrib/minizip
TOMMATH_DIR		= $(TOP_DIR)/libtommath
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150

151
152
153

154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
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		= 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}
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];\
			  $(TEST_LOAD_PRMS)
ZLIB_DLL_FILE		= zlib1.dll
TOMMATH_DLL_FILE		= libtommath.dll

SHARED_LIBRARIES 	= $(TCL_DLL_FILE) @ZLIB_DLL_FILE@ @TOMMATH_DLL_FILE@
STATIC_LIBRARIES	= $(TCL_LIB_FILE)

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@







<
<
<
<



















>
|

|
>
|




|
|
|










<







122
123
124
125
126
127
128




129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

171
172
173
174
175
176
177
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)')





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_FILE8		= tcldde$(DDEVER)${DLLSUFFIX}
DDE_LIB_FILE		= @LIBPREFIX@tcldde$(DDEVER)${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.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

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)


# 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@
227
228
229
230
231
232
233








234
235
236
237
238
239
240
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@









# Minizip
MINIZIP_OBJS = \
        adler32.$(HOST_OBJEXT) \
        compress.$(HOST_OBJEXT) \
        crc32.$(HOST_OBJEXT) \
        deflate.$(HOST_OBJEXT) \







>
>
>
>
>
>
>
>







225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
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) \
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

266
267
268
269

270
271
272
273
274
275
276
277
278
279
280

281
282
283
284
285
286

287
288
289
290
291
292
293
        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}" \
-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}

TCLTEST_OBJS = \
	tclTest.$(OBJEXT) \

	tclTestObj.$(OBJEXT) \
	tclTestProcBodyObj.$(OBJEXT) \
	tclThreadTest.$(OBJEXT) \
	tclWinTest.$(OBJEXT)

GENERIC_OBJS = \
	regcomp.$(OBJEXT) \
	regexec.$(OBJEXT) \
	regfree.$(OBJEXT) \
	regerror.$(OBJEXT) \
	tclAlloc.$(OBJEXT) \

	tclAssembly.$(OBJEXT) \
	tclAsync.$(OBJEXT) \
	tclBasic.$(OBJEXT) \
	tclBinary.$(OBJEXT) \
	tclCkalloc.$(OBJEXT) \
	tclClock.$(OBJEXT) \

	tclCmdAH.$(OBJEXT) \
	tclCmdIL.$(OBJEXT) \
	tclCmdMZ.$(OBJEXT) \
	tclCompCmds.$(OBJEXT) \
	tclCompCmdsGR.$(OBJEXT) \
	tclCompCmdsSZ.$(OBJEXT) \
	tclCompExpr.$(OBJEXT) \







|







<
|
|
>
|



>











>






>







254
255
256
257
258
259
260
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
        uncompr.$(HOST_OBJEXT) \
        zip.$(HOST_OBJEXT) \
        zutil.$(HOST_OBJEXT) \
        minizip.$(HOST_OBJEXT)

ZIP_INSTALL_OBJS =  @ZIP_INSTALL_OBJS@

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 = -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) \
343
344
345
346
347
348
349

350
351
352
353
354
355
356
	tclProc.$(OBJEXT) \
	tclProcess.$(OBJEXT) \
	tclRegexp.$(OBJEXT) \
	tclResolve.$(OBJEXT) \
	tclResult.$(OBJEXT) \
	tclScan.$(OBJEXT) \
	tclStringObj.$(OBJEXT) \

	tclStrToD.$(OBJEXT) \
	tclStubInit.$(OBJEXT) \
	tclThread.$(OBJEXT) \
	tclThreadAlloc.$(OBJEXT) \
	tclThreadJoin.$(OBJEXT) \
	tclThreadStorage.$(OBJEXT) \
	tclTimer.$(OBJEXT) \







>







352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
	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
	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_mp_exch.${OBJEXT} \
	bn_mp_expt_u32.${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_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_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} \







|

|


















>
>















>







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
	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_s_mp_div_3.${OBJEXT} \
	bn_mp_exch.${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

DDE_OBJS = tclWinDde.$(OBJEXT)

REG_OBJS = tclWinReg.$(OBJEXT)

STUB_OBJS = \
	tclStubLib.$(OBJEXT) \


	tclTomMathStubLib.$(OBJEXT) \
	tclOOStubLib.$(OBJEXT) \
	tclWinPanic.$(OBJEXT)

TCLSH_OBJS = tclAppInit.$(OBJEXT)

ZLIB_OBJS = \







>
>







462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

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

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}

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; \
	)
	(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)
	$(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@






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}
	@$(RM) ${TCL_STUB_LIB_FILE}
	@MAKE_STUB_LIB@ ${STUB_OBJS}
	@POST_MAKE_LIB@

${TCL_DLL_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

${TCL_LIB_FILE}: ${TCL_OBJS} ${DDE_OBJS} ${REG_OBJS}
	@$(RM) ${TCL_LIB_FILE}
	@MAKE_LIB@ ${TCL_OBJS} ${DDE_OBJS} ${REG_OBJS}
	@POST_MAKE_LIB@

${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









${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}
	@$(RM) ${TEST_EXE_FILE}
	$(CC) $(CFLAGS) $(TCLTEST_OBJS) tclTestMain.$(OBJEXT) $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(LIBS) \
        tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	$(COPY) tclsh.exe.manifest ${TEST_EXE_FILE}.manifest

# use pre-built zlib1.dll
${ZLIB_DLL_FILE}: ${TCL_STUB_LIB_FILE}




	@if test "@ZLIB_LIBS@set" != "${ZLIB_DIR_NATIVE}/win32/zdll.libset" ; then \
		$(COPY) $(ZLIB_DIR)/win64/${ZLIB_DLL_FILE} ${ZLIB_DLL_FILE}; \
	else \
		$(COPY) $(ZLIB_DIR)/win32/${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}/win32/tommath.libset" ; then \
		$(COPY) $(TOMMATH_DIR)/win64/${TOMMATH_DLL_FILE} ${TOMMATH_DLL_FILE}; \
	else \
		$(COPY) $(TOMMATH_DIR)/win32/${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)







|












<
<
<
<
<
<
<
<
<



|








|




>
>
>
>
>










|

|













|

|









>
>
>
>
>
>
>
>












|

>
>
>
>
|
|

|




>
>
>
>
|
|

|







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

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} ${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)"
	@( \









	  $(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}/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) ${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} ${DDE_OBJS} ${REG_OBJS}
	@$(RM) ${TCL_STUB_LIB_FILE}
	@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}
	@$(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

${TCL_LIB_FILE}: ${TCL_OBJS} tclWinPanic.$(OBJEXT) ${DDE_OBJS} ${REG_OBJS}
	@$(RM) ${TCL_LIB_FILE}
	@MAKE_LIB@ ${TCL_OBJS} tclWinPanic.$(OBJEXT) ${DDE_OBJS} ${REG_OBJS}
	@POST_MAKE_LIB@

${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}
	@$(RM) ${TEST_EXE_FILE}
	$(CC) $(CFLAGS) $(TCLTEST_OBJS) tclTestMain.$(OBJEXT) $(TCL_LIB_FILE) $(TCL_STUB_LIB_FILE) $(LIBS) \
        tclsh.$(RES) $(CC_EXENAME) $(LDFLAGS_CONSOLE)
	$(COPY) tclsh.exe.manifest ${TEST_EXE_FILE}.manifest

# 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}; \
	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)/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}; \
	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)/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

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)




tclWinDde.${OBJEXT}: tclWinDde.c
	$(CC) -c $(CC_SWITCHES) $(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







>
>
>



>
>
>









<
<
<
<
<







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

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 \





	$(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
		\
		-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)

















# 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 @DEPARG@ $(CC_OBJNAME)

tclTomMathStubLib.${OBJEXT}: tclTomMathStubLib.c
	$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @DEPARG@ $(CC_OBJNAME)

tclOOStubLib.${OBJEXT}: tclOOStubLib.c
	$(CC) -c $(CC_SWITCHES) -DSTATIC_BUILD @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







<


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>
>
>
>
>
>
>
>
>



|


|







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
		\
		-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)\"" \

		-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) @CFLAGS_NOLTO@ @DEPARG@ $(CC_OBJNAME)

tclOOStubLib.${OBJEXT}: tclOOStubLib.c
	$(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
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(MKDIR) "$$i"; \
		chmod 755 "$$i"; \
		else true; \
		fi; \
	    done;
	@for i in dde${DDEDOTVER} reg${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); \
	    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_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}"; \




	    fi
	@if [ -f $(REG_LIB_FILE) ]; then \
	    echo Installing $(REG_LIB_FILE); \
	    $(COPY) $(REG_LIB_FILE) "$(LIB_INSTALL_DIR)/reg${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"; \







|














|












>
>
>
>






|
|
|
>
>
>
>



|


<
<
<
<
<







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
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(MKDIR) "$$i"; \
		chmod 755 "$$i"; \
		else true; \
		fi; \
	    done;
	@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) @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)/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)/registry${REGDOTVER}"; \
	    fi






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
	    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; \
	    do \
	    $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \
	    done;
	@echo "Installing package cookiejar 0.2"
	@for j in $(ROOT_DIR)/library/cookiejar/*.{tcl,txt.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 opt 0.4.7";
	@for j in $(ROOT_DIR)/library/opt/*.tcl; \
	    do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	    done;
	@echo "Installing package msgcat 1.7.1 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl "$(MODULE_INSTALL_DIR)/9.0/msgcat-1.7.1.tm";
	@echo "Installing package tcltest 2.5.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 platform::shell 1.1.4 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/shell.tcl "$(MODULE_INSTALL_DIR)/9.0/platform/shell-1.1.4.tm";
	@echo "Installing encodings";
	@for i in $(ROOT_DIR)/library/encoding/*.enc; do \
		$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done;

install-tzdata:
	@echo "Installing time zone data"
	@$(TCL_EXE) "$(ROOT_DIR)/tools/installData.tcl" \
	    "$(ROOT_DIR)/library/tzdata" "$(SCRIPT_INSTALL_DIR_NATIVE)/tzdata"







|
<



|
|


|
|

|
<




|
|
|
|



|







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
	    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; do \

	    $(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)"; \
	    done;
	@echo "Installing package cookiejar 0.2"
	@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.10b2 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/http/http.tcl "$(MODULE_INSTALL_DIR)/9.0/http-2.10b2.tm";
	@echo "Installing package opt 0.4.7";
	@for j in $(ROOT_DIR)/library/opt/*.tcl; do \

	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	    done;
	@echo "Installing package msgcat 1.7.1 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl "$(MODULE_INSTALL_DIR)/9.0/msgcat-1.7.1.tm";
	@echo "Installing package tcltest 2.5.8 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl "$(MODULE_INSTALL_DIR)/9.0/tcltest-2.5.8.tm";
	@echo "Installing package platform 1.0.19 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl "$(MODULE_INSTALL_DIR)/9.0/platform-1.0.19.tm";
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/shell.tcl "$(MODULE_INSTALL_DIR)/9.0/platform/shell-1.1.4.tm";
	@echo "Installing encodings";
	@for i in $(ROOT_DIR)/library/encoding/*.enc ; do \
		$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done;

install-tzdata:
	@echo "Installing time zone data"
	@$(TCL_EXE) "$(ROOT_DIR)/tools/installData.tcl" \
	    "$(ROOT_DIR)/library/tzdata" "$(SCRIPT_INSTALL_DIR_NATIVE)/tzdata"
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

depend:

Makefile: $(SRC_DIR)/Makefile.in
	./config.status

cleanhelp:
	$(RM) *.hlp *.cnt *.GID *.rtf man2tcl.exe

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) 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

#
# Bundled package targets
#

PKG_CFG_ARGS		= @PKG_CFG_ARGS@
PKG_DIR			= ./pkgs







|




|

<




|







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

depend:

Makefile: $(SRC_DIR)/Makefile.in
	./config.status

cleanhelp:
	$(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 *.zip
	$(RM) minizip${HOST_EXEEXT} *.${HOST_OBJEXT}

	$(RMDIR) *.vfs

distclean: distclean-packages clean
	$(RM) Makefile config.status config.cache config.log tclConfig.sh \
		config.status.lineno tclsh.exe.manifest tclUuid.h

#
# Bundled package targets
#

PKG_CFG_ARGS		= @PKG_CFG_ARGS@
PKG_DIR			= ./pkgs
1089
1090
1091
1092
1093
1094
1095










1096
1097
1098
1099
1100
1101
1102
	    "$(GENERIC_DIR_NATIVE)/tcl.decls" \
	    "$(GENERIC_DIR_NATIVE)/tclInt.decls" \
	    "$(GENERIC_DIR_NATIVE)/tclTomMath.decls"
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/genStubs.tcl" \
	    "$(GENERIC_DIR_NATIVE)" \
	    "$(GENERIC_DIR_NATIVE)/tclOO.decls"











#
# 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.
#








>
>
>
>
>
>
>
>
>
>







1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
	    "$(GENERIC_DIR_NATIVE)/tcl.decls" \
	    "$(GENERIC_DIR_NATIVE)/tclInt.decls" \
	    "$(GENERIC_DIR_NATIVE)/tclTomMath.decls"
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/genStubs.tcl" \
	    "$(GENERIC_DIR_NATIVE)" \
	    "$(GENERIC_DIR_NATIVE)/tclOO.decls"

$(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!"

genscript:
	$(TCL_EXE) "$(ROOT_DIR_NATIVE)/tools/makeHeader.tcl" \
		"$(ROOT_DIR_NATIVE)/tools/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
#

.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

# DO NOT DELETE THIS LINE -- make depend depends on it.







|
|


1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
#

.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 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
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

2. Compiling Tcl
----------------

In order to compile Tcl for Windows, you need the following:

	Tcl 9.0 Source Distribution (plus any patches)

	and


	Visual C++ 6 or newer










	or

	Linux + MinGW-w64 [http://mingw-w64.sourceforge.net/]
	    (win32 or win64)

	or

	Cygwin + MinGW-w64 [http://cygwin.com/install.html]
	    (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)

	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











|










>
|
>
>
>
>
>
>
>
>
>



|




|
<
<
<
<
<




|
|
<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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:

	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

	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

	Darwin + MinGW-w64 [https://www.mingw-w64.org/]
	    (win32 or win64)

	or

	Msys + MinGW-w64 [https://www.mingw-w64.org/]





	    (win32 or win64)

	or

	LLVM MinGW [https://github.com/mstorsjo/llvm-mingw/]
	    (win32 or win64, IX86, AMD64 or ARM64)







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

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 option. Make sure that the x86_64-w64-mingw32
compiler is present. For Cygwin this 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: Tcl no longer provides support for Win32s.



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.







>
|
|










|
|
|

|
>
>













63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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 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,
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 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
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
nmake -nologo -f makefile.vc shell OPTS=%OPTS% %1
if errorlevel 1 goto error

set OPTS=
set SYMBOLS=
goto end








|
|







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
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
#! /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
test \$(( 1 + 1 )) = 2 || 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 [email protected] 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


|


|
>










|
>






|
|




>




>
>
>
>
>
>
>
>



<
<
<
<
<
<
<
<
|
|
<
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
>
>
|
<
<
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>


|








<
<
<
<
<
<
<








>
|
>
>
>
|





|





|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




















|
|
|




|
>






|
|




>














|
>

|
|
>


>
>






|
>

|
|
>

|
>

|
|




>
|
>
>
>





|

|
>

|
>







>
>
>
>
>
|
|
>

>
>
|
<


|
>
















|
|



|
>
|
|
|
|
|

|





|
>



















>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47








48
49

50
51






52







53
54
55
56


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113




















114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
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.72 for tcl 9.0.
#
#
# 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 ${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 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








IFS=" ""	$as_nl"


PS1='$ '
PS2='> '






PS4='+ '








# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL


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 ${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









# 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 #(((
    '') 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'
# 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
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi






















# 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'.
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 \${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 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 :

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 :
  as_have_required=yes
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 :

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 #(((
    '') 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
	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
		    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_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 #(
  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



      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'.
printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi

    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
    printf "%s\n" "$0: Please tell [email protected] 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 ;;
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
  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







|








|







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=`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 ||
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
} # 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







|
>




|
|


|
>







|
>




|
|


|
>













|

|







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 :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
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 :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
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
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  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
  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







|







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 ||
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
  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







>
>











|













>
>
>
>












>
>
>
>
>
>












|
|
|







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" ||
    { 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'.
    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
  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,







|
>


|
>







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_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_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
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="../generic/tcl.h"
# Factoring default headers for most tests.
ac_includes_default="\
#include <stdio.h>
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_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_UNISTD_H
# include <unistd.h>
#endif"


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







|
|
|
|
|
|




|
|
|

|
<
<
<

<
<
<
<
<


<
<
<


<
<
<






>
>
>
>
>
>
>
>
>




>















<
<
<
<
<
<







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='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 <stddef.h>
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H



# include <stdlib.h>





#endif
#ifdef HAVE_STRING_H



# include <string.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_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
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







<







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_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
TCL_MINOR_VERSION
TCL_MAJOR_VERSION
TCL_VERSION
MACHINE
TCL_WIN_VERSION
VC_MANIFEST_EMBED_EXE
VC_MANIFEST_EMBED_DLL

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


TOMMATH_OBJS
ZLIB_OBJS
TOMMATH_LIBS
ZLIB_LIBS
TOMMATH_DLL_FILE
ZLIB_DLL_FILE

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







>













>
>






>











<
<
<







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



OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
CC
751
752
753
754
755
756
757

758
759
760
761
762
763
764
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir

localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir







>







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
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'







>


|







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_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

  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=*)







<
<







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



  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
  | --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







|

|







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'"
    ac_useropt_orig=$ac_useropt
    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
  -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







|

|







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'"
    ac_useropt_orig=$ac_useropt
    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
    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 ;;








>
>
>
>
>
>
>
>
>







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
  -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







|

|













|

|







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'"
    ac_useropt_orig=$ac_useropt
    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'"
    ac_useropt_orig=$ac_useropt
    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
  -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.







|
|







|






|

|















|







|
















|







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"
    ;;

  *=*)
    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.
    printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
      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" ;;
    *)     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 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'
# 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
  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







|







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 ||
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
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







|







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_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
#
# 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 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)







|













|

|

|







|
|
|
|










>








|











|
>
>







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 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
      --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]
  --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/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
  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
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|^\.[\\/]||'`
  # 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







|


















|

|







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
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=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  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
    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. ##
## ------------------------ ##

# 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
  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
  (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
  test $ac_status = 0; } && {
	 test -z "$ac_c_werror_flag" ||
	 test ! -s conftest.err
       } && test -s conftest.$ac_objext; then :

  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	ac_retval=1

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_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
  (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
  test $ac_status = 0; } > conftest.i && {
	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
	 test ! -s conftest.err

       }; then :
  ac_retval=0
else
  $as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

    ac_retval=1

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_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
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
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_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_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_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"
  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
  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

  $ $0 $@

_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##







|
>







|








|
|

|
















|






|







|



|
>

|
|


|
>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>













|







|



>
|

|
|


|
>





|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
|
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
>
|
<
<
<
<
<
<
<
<
<
<

<




|
|

|







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 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
      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.72

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 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\""
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
  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 :
  ac_retval=0
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	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\""
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
  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 :
  ac_retval=0
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

    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=




























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.72.  Invocation command line was

  $ $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

_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








>
|
>
>
>
|







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 #(((
    '') 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
  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.







|







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=`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

# 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







>
>




|










|
|







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

    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_*) { 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
      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





# 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"
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








|







|

|




|







|

|





|







|
|













|



<
|
<

<
|
<

<
|
<

<
|
<

<
|
<

<
|
<




<
<

<
|
<
<
<
<

|
<

|
<

>
|

|
>
>
>
>
>
|
|
|


|
|

|







|
|






|
|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










|
|


|
|








|
|


|
|


|
|
|
|





|









|
|
|
|
>
|













>









|







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

    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=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
      esac
      printf "%s\n" "$ac_var='\''$ac_val'\''"
    done | sort
    echo

    if test -n "$ac_subst_files"; then
      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=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
	esac
	printf "%s\n" "$ac_var='\''$ac_val'\''"
      done | sort
      echo
    fi

    if test -s confdefs.h; then
      printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
      echo
      cat confdefs.h
      echo
    fi
    test "$ac_signal" != 0 &&
      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

printf "%s\n" "/* confdefs.h */" > confdefs.h

# Predefined preprocessor variables.


printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h



printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h



# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.


if test -n "$CONFIG_SITE"; then

  ac_site_files="$CONFIG_SITE"




elif test "x$prefix" != xNONE; then
  ac_site_files="$prefix/share/config.site $prefix/etc/config.site"

else
  ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"

fi

for ac_site_file in $ac_site_files
do
  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" \
      || { { 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; }
  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
    { 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
  { 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,)
      { 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)
      { 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
	  { 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
	  { 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
	{ 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=`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
  { 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="b2"
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
#------------------------------------------------------------------------

# 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
  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

  test -z "$as_dir" && as_dir=.



    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}gcc"
    $as_echo "$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
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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="gcc"
    $as_echo "$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
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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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;}
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
  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

  test -z "$as_dir" && as_dir=.



    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}cc"
    $as_echo "$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
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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
       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
    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+' '}$@"
  fi
fi
fi

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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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$ac_prog"
    $as_echo "$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
CC=$ac_cv_prog_CC
if test -n "$CC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
$as_echo "$CC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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="$ac_prog"
    $as_echo "$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
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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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;}
ac_tool_warned=yes ;;
esac
    CC=$ac_ct_CC
  fi










































































































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;}
as_fn_error $? "no acceptable C compiler found in \$PATH
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
set X $ac_compile
ac_compiler=$2
for ac_option in --version -v -V -qversion; 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
  (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
  test $ac_status = 0; }
done

cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  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[^ ]*//'`

# 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
  (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'
# 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;
	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'
	# 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=''

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
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;}
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; }

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; }
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; }
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; }; 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;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }

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; }

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 ()
{
FILE *f = fopen ("conftest.out", "w");


 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; }
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
  (eval "$ac_link") 2>&5
  ac_status=$?
  $as_echo "$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
  (eval "$ac_try") 2>&5
  ac_status=$?
  $as_echo "$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; }
    fi
  fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
$as_echo "$cross_compiling" >&6; }

rm -f conftest.$ac_ext conftest$ac_cv_exeext 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
/* end confdefs.h.  */

int
main ()
{

  ;
  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
  (eval "$ac_compile") 2>&5
  ac_status=$?
  $as_echo "$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
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;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }

fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
$as_echo "$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
/* end confdefs.h.  */

int
main ()
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  ac_compiler_gnu=yes
else
  ac_compiler_gnu=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
$as_echo "$ac_cv_c_compiler_gnu" >&6; }


if test $ac_compiler_gnu = yes; then
  GCC=yes
else
  GCC=
fi
ac_test_CFLAGS=${CFLAGS+set}
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
   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 ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  ac_cv_prog_cc_g=yes
else
  CFLAGS=""
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :


else
  ac_c_werror_flag=$ac_save_c_werror_flag
	 CFLAGS="-g"
	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main ()
{

  ;
  return 0;
}
_ACEOF
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

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag

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
  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



{ $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
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;
}

/* 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 \
	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"; then :

  ac_cv_prog_cc_c89=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
  test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC

fi
# AC_CACHE_VAL
case "x$ac_cv_prog_cc_c89" in
  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; } ;;
  *)

    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; } ;;

esac

if test "x$ac_cv_prog_cc_c89" != xno; then :



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
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; }
#endif

_ACEOF
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
  test "$ac_cv_c_inline" != no && break
done


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5
$as_echo "$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
  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

  test -z "$as_dir" && as_dir=.



    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_AR="${ac_tool_prefix}ar"
    $as_echo "$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
AR=$ac_cv_prog_AR
if test -n "$AR"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
$as_echo "$AR" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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_AR="ar"
    $as_echo "$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
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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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;}
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
  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

  test -z "$as_dir" && as_dir=.



    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_RANLIB="${ac_tool_prefix}ranlib"
    $as_echo "$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
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
$as_echo "$RANLIB" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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_RANLIB="ranlib"
    $as_echo "$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
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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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;}
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
  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

  test -z "$as_dir" && as_dir=.



    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_RC="${ac_tool_prefix}windres"
    $as_echo "$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
RC=$ac_cv_prog_RC
if test -n "$RC"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5
$as_echo "$RC" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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_RC="windres"
    $as_echo "$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
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; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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;}
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; }
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
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

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; }
  SET_MAKE=
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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 :

  withval=$with_encoding; with_tcencoding=${withval}
fi


    if test x"${with_tcencoding}" != x ; then
	cat >>confdefs.h <<_ACEOF
#define TCL_CFGVAL_ENCODING "${with_tcencoding}"
_ACEOF

    else
	$as_echo "#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; }
    # Check whether --enable-shared was given.
if test "${enable_shared+set}" = set; then :

  enableval=$enable_shared; tcl_ok=$enableval
else
  tcl_ok=yes
fi


    if test "${enable_shared+set}" = set; then
	enableval="$enable_shared"
	tcl_ok=$enableval
    else
	tcl_ok=yes
    fi

    if test "$tcl_ok" = "yes" ; then
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5
$as_echo "shared" >&6; }
	SHARED_BUILD=1
    else
	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5
$as_echo "static" >&6; }
	SHARED_BUILD=0

$as_echo "#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 \
		  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

fi


done






    # 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; }
    # Check whether --enable-64bit was given.
if test "${enable_64bit+set}" = set; then :

  enableval=$enable_64bit; do64bit=$enableval
else
  do64bit=no

fi

    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5
$as_echo "$do64bit" >&6; }

    # Set some defaults (may get changed below)
    EXTRA_CFLAGS=""

$as_echo "#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
  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

  test -z "$as_dir" && as_dir=.



    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_CYGPATH="cygpath -m"
    $as_echo "$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
CYGPATH=$ac_cv_prog_CYGPATH
if test -n "$CYGPATH"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5
$as_echo "$CYGPATH" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "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
  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

  test -z "$as_dir" && as_dir=.



    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_WINE="wine"
    $as_echo "$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
WINE=$ac_cv_prog_WINE
if test -n "$WINE"; then
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINE" >&5
$as_echo "$WINE" >&6; }
else
  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi



    SHLIB_SUFFIX=".dll"

    # MACHINE is IX86 for LINK, but this is used by the manifest,
    # which requires x86|amd64|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
/* end confdefs.h.  */

	    #ifndef _WIN32
		#error cross-compiler
	    #endif

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  ac_cv_cross=no
else
  ac_cv_cross=yes

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5
$as_echo "$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"
	    ;;







	    *)
		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"
	    ;;







>
>
>
>
>
>
>
>
>









|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|








|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|







|
|












|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|








|
|
|
>
|
|
|







>
|
>
>
>

|
|




|















|


|
>



|
|

|
|










|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|












|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|











|
|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
|

|


|


|






|









|







|











|
|
|




















|


|
|
>
|
|














|




|










|
|
>

|
>
|
|
|


|
|

|
|
|
|
>

|
|
|
|




|
|






|


|
|
>
|
|
|
|









|
|
|

|
>


|
|








|


>
>









|
|







|


|







|


|






|
|
|
|
|



|
|

|
>

|
|
|
>
|
|
|



|













|


|
|
>








|
|


|
|

|
>

|
>

|
|


|
|
|
>
|
|
|



|









|
>

|
|
>

|

|
>

|
|
>
>





|

|
|
|
>
|
|
|







|






|
>

|
|




|






|
>

|
|





|






|
>


|
>

|
>

|
|
>

|
|
|














>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
<


|
>


|



|
|

|
|
<
<
<
|
|
|
<
>
|
>
>
>
>
|
|
>

>
|
|
>
>









|
|
|
>
|
|
|





|
|



|
>


|


|
>

|
|
















<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|








|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|







|
|











|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|








|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|







|
|











|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|








|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|







|
|













|
|

|
|
>
|
|
|











|
>


|
|


|
|


















|
>





<
|
<


|










|
|

|
>

|
|
<
|
<
<
<
<
<
<
|


|
|


|
|


|











<
|
<
>
|
|
|
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|

|

>
|

>

>




|
|

|
>

|
|
>


|
|




|




|
|
|
>
|
|
|






>
|
>
>
>

|

|







|
>



|
|

|
|





|
|
|
>
|
|
|






>
|
>
>
>

|

|






|
>



|
|

|
|







|




|
|
|
>
|
|
|







|






|
>

|
|
>

|
|
>

|
|










>
>
>
>
>
>
>







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
{ 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}gcc"
    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 "gcc", so it can be a program name with args.
set dummy gcc; 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="gcc"
    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

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
{ 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}cc"
    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
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
{ 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 #(((
    '') 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
       ac_prog_rejected=yes
       continue
     fi
    ac_cv_prog_CC="cc"
    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+' '}$@"
  fi
fi
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 "$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
{ 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$ac_prog"
    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


    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
{ 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="$ac_prog"
    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


  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:)
{ 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" && { { 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; }

# Provide some information about the compiler.
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 -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\""
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
  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 (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.
{ 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\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_link_default") 2>&5
  ac_status=$?
  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+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'
	# 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 case e in #(
  e) ac_file='' ;;
esac
fi
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

{ { 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 case e in #(
  e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; } ;;
esac
fi
{ 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
{ 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\""
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; }
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 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; } ;;
esac
fi
rm -f conftest conftest$ac_cv_exeext
{ 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 (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.
{ 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\""
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; }
  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\""
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
    cross_compiling=no
  else
    if test "$cross_compiling" = maybe; then
	cross_compiling=yes
    else
	{ { 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
{ 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.o conftest.obj conftest.out
ac_clean_files=$ac_clean_files_save
{ 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 (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\""
printf "%s\n" "$ac_try_echo"; } >&5
  (eval "$ac_compile") 2>&5
  ac_status=$?
  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 case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&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 $? "cannot compute suffix of object files: cannot compile
See 'config.log' for more details" "$LINENO" 5; } ;;
esac
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext ;;
esac
fi
{ 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
{ 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 (void)
{
#ifndef __GNUC__
       choke me
#endif

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_compiler_gnu=yes
else case e in #(
  e) ac_compiler_gnu=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
 ;;
esac
fi
{ 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+y}
ac_save_CFLAGS=$CFLAGS
{ 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
else case e in #(
  e) CFLAGS=""
      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

int
main (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :

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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_g=yes
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
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
   ac_c_werror_flag=$ac_save_c_werror_flag ;;
esac
fi
{ 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 :
  { 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.  */





















$ac_c_conftest_c89_program



























_ACEOF
for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"

do
  CC="$ac_save_CC $ac_arg"
  if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_prog_cc_c89=$ac_arg
fi
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 ;;
esac
fi

if test "x$ac_cv_prog_cc_c89" = 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_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
  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


{ 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 (void) {return 0; }
$ac_kw foo_t foo (void) {return 0; }
#endif

_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_c_inline=$ac_kw
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
  test "$ac_cv_c_inline" != no && break
done
 ;;
esac
fi
{ 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






























































































































































































































































































































































































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
{ 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 #(((
    '') 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_AR="${ac_tool_prefix}ar"
    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
AR=$ac_cv_prog_AR
if test -n "$AR"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
printf "%s\n" "$AR" >&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_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
{ 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 #(((
    '') 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_AR="ar"
    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_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
printf "%s\n" "$ac_ct_AR" >&6; }
else
  { 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:)
{ 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
{ 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 #(((
    '') 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_RANLIB="${ac_tool_prefix}ranlib"
    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
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
printf "%s\n" "$RANLIB" >&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_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
{ 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 #(((
    '') 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_RANLIB="ranlib"
    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_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
  { 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:)
{ 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
{ 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 #(((
    '') 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_RC="${ac_tool_prefix}windres"
    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
RC=$ac_cv_prog_RC
if test -n "$RC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RC" >&5
printf "%s\n" "$RC" >&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_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
{ 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 #(((
    '') 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_RC="windres"
    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_RC=$ac_cv_prog_ac_ct_RC
if test -n "$ac_ct_RC"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5
printf "%s\n" "$ac_ct_RC" >&6; }
else
  { 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:)
{ 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.
#--------------------------------------------------------------------

{ 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=`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 ;;
esac
fi
if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
printf "%s\n" "yes" >&6; }
  SET_MAKE=
else
  { 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+y}
then :
  withval=$with_encoding; with_tcencoding=${withval}
fi


    if test x"${with_tcencoding}" != x ; then

	printf "%s\n" "#define TCL_CFGVAL_ENCODING \"${with_tcencoding}\"" >>confdefs.h


    else
	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.
#--------------------------------------------------------------------


    { 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+y}
then :
  enableval=$enable_shared; tcl_ok=$enableval
else case e in #(
  e) tcl_ok=yes ;;

esac






fi

    if test "$tcl_ok" = "yes" ; then
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared" >&5
printf "%s\n" "shared" >&6; }
	SHARED_BUILD=1
    else
	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static" >&5
printf "%s\n" "static" >&6; }
	SHARED_BUILD=0

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.
#--------------------------------------------------------------------


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


    # Step 0: Enable 64 bit support?

    { 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+y}
then :
  enableval=$enable_64bit; do64bit=$enableval
else case e in #(
  e) do64bit=no ;;
esac
fi

    { 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=""

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
{ 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 #(((
    '') 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_CYGPATH="cygpath -m"
    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 ;;
esac
fi
CYGPATH=$ac_cv_prog_CYGPATH
if test -n "$CYGPATH"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5
printf "%s\n" "$CYGPATH" >&6; }
else
  { 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
{ 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 #(((
    '') 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_WINE="wine"
    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
WINE=$ac_cv_prog_WINE
if test -n "$WINE"; then
  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $WINE" >&5
printf "%s\n" "$WINE" >&6; }
else
  { 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|arm64|ia64.
    MACHINE="X86"

    if test "$GCC" = "yes"; then

      { 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_cross=no
else case e in #(
  e) ac_cv_cross=yes ;;
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_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

    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; }
	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
  test $ac_status = 0; }; } ; then
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
	    CYGPATH=echo
	fi
	conftest=
	cyg_conftest=
    fi

    if test "$CYGPATH" = "echo"; then
        DEPARG='"$<"'
    else
        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
/* end confdefs.h.  */

		#ifdef _WIN32
		    #error win32
		#endif

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  ac_cv_win32=no
else
  ac_cv_win32=yes

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_win32" >&5
$as_echo "$ac_cv_win32" >&6; }
	if test "$ac_cv_win32" != "yes"; then
	    as_fn_error $? "${CC} cannot produce win32 executables." "$LINENO" 5
	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

# 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
  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>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; } && {
	 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

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 ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  ac_cv_municode=yes
else
  ac_cv_municode=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: $ac_cv_municode" >&5
$as_echo "$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
























    fi





















































































    { $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler flags" >&5
$as_echo_n "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"
	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; }
	    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; }

	    # 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
	    fi








|
|





|

|
|

|
|

















|
|
|
>
|
|
|







|






|
>

|
|
>

|
|
>

|
|



>
>
>


|
|
|
>
|
|
|






|






|







|






>
|

|
|


|
>

















|






|
>

|
|
>

|

|
>

|
|






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|





|














|
|





|
|







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

    if test "$GCC" = "yes" && test "$CYGPATH" != "echo" ; then
	conftest=/tmp/conftest.rc
	echo "STRINGTABLE BEGIN" > $conftest
	echo "101 \"name\"" >> $conftest
	echo "END" >> $conftest

	{ 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=$?
  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
  test $ac_status = 0; }; } ; then
	    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }
	else
	    { 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='"$<"'
    else
        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"
	{ 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  ac_cv_win32=no
else case e in #(
  e) ac_cv_win32=yes ;;
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_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"
	{ 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.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\""
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
  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 :
  ac_retval=0
else case e in #(
  e) printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

	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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  ac_cv_municode=yes
else case e in #(
  e) ac_cv_municode=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
	 ;;
esac
fi
{ 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
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

    { 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 -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
            { 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
            { 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
	    fi

4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
	LDFLAGS_OPTIMIZE=

	case "${CC}" in
	    *++)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wno-format"
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -Wdeclaration-after-statement"
		;;
	esac

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \$@"
	CC_EXENAME="-o \$@"








|







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 -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
	#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; }





		;;
	    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; }
		;;
	    *)
		cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h.  */

		    #ifndef _WIN64
			#error 32-bit
		    #endif

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_win_64bit=yes
else
  tcl_win_64bit=no


fi
rm -f core conftest.err conftest.$ac_objext 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; }
		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; }
	    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; }
	    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"







|
|
>
>
>
>
>



|
|










|






|
>

|
|
|
>

|

|
|
|
|






|
|





|
|







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
		{ 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"
		{ 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_win_64bit=yes
else case e in #(
  e) tcl_win_64bit=no
		 ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
		if test "$tcl_win_64bit" = "yes" ; then
		    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
            { 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
            { 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
	LIBFLAGSUFFIX=""

	if test "$do64bit" != "no" ; then
	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		    ;;



		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; }
	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}"
	    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"

	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







>
>
>




|
|















<
|
















|







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
	    { 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"

	    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 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
	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

    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 :

  tcl_cv_seh=no
else












































  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 :

  tcl_cv_seh=yes
else
  tcl_cv_seh=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: $tcl_cv_seh" >&5
$as_echo "$tcl_cv_seh" >&6; }
	if test "$tcl_cv_seh" = "no" ; then

$as_echo "#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
/* end confdefs.h.  */

#	    define WIN32_LEAN_AND_MEAN
#	    include <windows.h>
#	    undef WIN32_LEAN_AND_MEAN

int
main ()
{

		EXCEPTION_DISPOSITION x;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_eh_disposition=yes
else
  tcl_cv_eh_disposition=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5
$as_echo "$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 ()
{

		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
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 :


$as_echo "#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
/* end confdefs.h.  */

int
main ()
{

		  union foo { int i; double d; };
		  union foo f = (union foo) (int) 0;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_cast_to_union=yes
else
  tcl_cv_cast_to_union=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


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

$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h

	fi
    fi

    # DL_LIBS is empty, but then we match the Unix version







# Cross-compiling







|




|
|
|
>
|
|
|
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|


















|
>

|
|
>


|
>


|
>

|
|


|









|
|
|
>
|
|
|







|








|
>

|
|
>

|
|
>

|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<

<
<
<
<
<
<
<
<
|
<

<
<
<
<
<
<
<
<
<
|
|
>

|


<






|
|
|
>
|
|
|



|









|
>

|
|
>

|
|
>

|
|


|





>







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
	printf "%s\n" "#define TCL_CFG_DO64BIT 1" >>confdefs.h

    fi

    if test "${GCC}" = "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 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 :
  tcl_cv_seh=yes
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 ;;
esac
fi

	 ;;
esac
fi
{ 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

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.
	#
	{ 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 (void)
{

		EXCEPTION_DISPOSITION x;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_eh_disposition=yes
else case e in #(
  e) tcl_cv_eh_disposition=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_eh_disposition" >&5
printf "%s\n" "$tcl_cv_eh_disposition" >&6; }
	if test "$tcl_cv_eh_disposition" = "no" ; then

























printf "%s\n" "#define EXCEPTION_DISPOSITION int" >>confdefs.h












	fi











	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 :

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.

	{ 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 (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 :
  tcl_cv_cast_to_union=yes
else case e in #(
  e) tcl_cv_cast_to_union=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_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
    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

#------------------------------------------------------------------------
#	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 :


  enableval="$enable_shared"
  tcl_ok=$enableval

else

  tcl_ok=yes


fi


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

  if test "$do64bit" != "no"; then :



$as_echo "#define MP_64BIT 1" >>confdefs.h




    if test "$GCC" == "yes"; then :


      ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64/libz.dll.a

      TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win64/libtommath.dll.a




else














      ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64/zdll.lib

      TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win64/tommath.lib















fi

else

    ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win32/zdll.lib

    TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win32/tommath.lib



fi

else

  ZLIB_OBJS=\${ZLIB_OBJS}

  TOMMATH_OBJS=\${TOMMATH_OBJS}



fi

$as_echo "#define HAVE_ZLIB 1" >>confdefs.h


ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "$ac_includes_default"
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
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 :


$as_echo "#define HAVE_UINTPTR_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; }
    if test "$tcl_cv_uintptr_t" != none; then

cat >>confdefs.h <<_ACEOF
#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 :

  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
    #

    { $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

	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


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; }
    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; }
    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

    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






#--------------------------------------------------------------------
# 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
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

int
main ()
{

  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_findex_enums=yes
else
  tcl_cv_findex_enums=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_findex_enums" >&5
$as_echo "$tcl_cv_findex_enums" >&6; }
if test "$tcl_cv_findex_enums" = "no"; then

$as_echo "#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
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <intrin.h>

int
main ()
{

  __cpuidex(0,0,0);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :

  tcl_cv_intrinsics=yes
else
  tcl_cv_intrinsics=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_intrinsics" >&5
$as_echo "$tcl_cv_intrinsics" >&6; }
if test "$tcl_cv_intrinsics" = "yes"; then

$as_echo "#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
/* end confdefs.h.  */

#include <wspiapi.h>

int
main ()
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_wspiapi_h=yes
else
  tcl_cv_wspiapi_h=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_wspiapi_h" >&5
$as_echo "$tcl_cv_wspiapi_h" >&6; }
if test "$tcl_cv_wspiapi_h" = "yes"; then

$as_echo "#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
/* end confdefs.h.  */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

int
main ()
{

  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :

  tcl_cv_findex_enums=yes
else
  tcl_cv_findex_enums=no

fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext


fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_findex_enums" >&5
$as_echo "$tcl_cv_findex_enums" >&6; }
if test "$tcl_cv_findex_enums" = "no"; then

$as_echo "#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; }
    # Check whether --enable-symbols was given.
if test "${enable_symbols+set}" = set; then :

  enableval=$enable_symbols; tcl_ok=$enableval
else
  tcl_ok=no

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

	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }

	$as_echo "#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; }
	fi
    fi



    if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then

$as_echo "#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


$as_echo "#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; }
	else
	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
$as_echo "enabled $tcl_ok debugging" >&6; }
	fi
    fi


#--------------------------------------------------------------------
# Embed the manifest if we can determine how
#--------------------------------------------------------------------



















































































































































































































































































    { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to embed manifest" >&5
$as_echo_n "checking whether to embed manifest... " >&6; }
    # Check whether --enable-embedded-manifest was given.
if test "${enable_embedded_manifest+set}" = set; then :

  enableval=$enable_embedded_manifest; embed_ok=$enableval
else
  embed_ok=yes

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 :


	# 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 \[email protected] ; then mt.exe -nologo -manifest \[email protected]  -outputresource:\$@\;2 ; fi"
	VC_MANIFEST_EMBED_EXE="if test -f \[email protected] ; then mt.exe -nologo -manifest \[email protected]  -outputresource:\$@\;1 ; fi"
	result=yes
	if test "x" != x ; then
	    result="yes ()"
	fi

fi
rm -f conftest*

    fi
    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $result" >&5
$as_echo "$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_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

 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\""
else

 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}\""

# 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}"
else
    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















# empty on win















|
>




|
|

|
>

>
>
|
>






|

|
>


|

>
>
>
|
>

|

|

>
>

|
>
>

>
>
>
>
>
>
>
>
>
>
>
|

|

>
>

>
>
>
>
>
>
>
>
>
>
>


|
|




|
>


|
|




|
>


|

|
<
<

|
<

<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<

<
<
<
<
<
<
|

<

<
<
<
<
<
|
<
<
|
<
<
|
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|

|
<
<

<


<






|
>

|
|
>











|
|
|
>
|
|
|












|
>











|
|
|
>
|
|
|










|
>

|
|








|
|

|
>
|
|
|












|
>





|
|



|
|









|
|
|
>
|
|
|












|
>




|
|


|
|








|
|







|





|
|




|

<
<
<


|

<
>
|
|
<

|
|

















|
|
|
>
|
|
|







|









|
>

|
|
>

|
|
>

|
|


|





|
|
|
>
|
|
|








|








|
>

|
|
>

|

|
>

|
|


|





|
|
|
>
|
|
|





|






|
>

|
|
>

|
|
>

|
|


|







|
|
|
>
|
|
|







|









|
>

|
|
>

|
|
>

|
|


|










|
|

|
>

|
|
>







|

|
|

|





|
|







|





|


|





|
|

|
|








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|

|
>

|
|
>


















|
>















|


|
|


















|
|





|
>


>


|
|






<



<




















|

|












|
















<







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 :

  enableval="$enable_shared"
  tcl_ok=$enableval

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 :

  ZLIB_DLL_FILE=\${ZLIB_DLL_FILE}

  TOMMATH_DLL_FILE=\${TOMMATH_DLL_FILE}


printf "%s\n" "#define TCL_WITH_EXTERNAL_TOMMATH 1" >>confdefs.h

  if test "$do64bit" != "no"
then :


printf "%s\n" "#define MP_64BIT 1" >>confdefs.h

    if test "$do64bit" = "arm64"
then :

      if test "$GCC" == "yes"
then :

        ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win64-arm/libz.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 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/libz.dll.a

        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 case e in #(
  e)
    ZLIB_LIBS=\${ZLIB_DIR_NATIVE}/win32/zdll.lib

    TOMMATH_LIBS=\${TOMMATH_DIR_NATIVE}/win32/tommath.lib

   ;;
esac
fi

else case e in #(
  e)
  ZLIB_OBJS=\${ZLIB_OBJS}

  TOMMATH_OBJS=\${TOMMATH_OBJS}

 ;;
esac
fi

printf "%s\n" "#define HAVE_ZLIB 1" >>confdefs.h

TCL_ZLIB_LIB_NAME=$zlib_lib_name



TCL_TOMMATH_LIB_NAME=$tommath_lib_name



ac_fn_c_check_type "$LINENO" "intptr_t" "ac_cv_type_intptr_t" "










#include <stdint.h>






"
















if test "x$ac_cv_type_intptr_t" = xyes



then :








printf "%s\n" "#define HAVE_INTPTR_T 1" >>confdefs.h








fi


ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "


#include <stdint.h>






"














if test "x$ac_cv_type_uintptr_t" = xyes
then :

printf "%s\n" "#define HAVE_UINTPTR_T 1" >>confdefs.h





fi



#--------------------------------------------------------------------
#	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" ; 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
    #

    { 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]*.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"
	{ 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=""
	{ 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=""

    { 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






#--------------------------------------------------------------------
# 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.

{ 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 (void)
{

  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_findex_enums=yes
else case e in #(
  e) tcl_cv_findex_enums=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_findex_enums" >&5
printf "%s\n" "$tcl_cv_findex_enums" >&6; }
if test "$tcl_cv_findex_enums" = "no"; then

printf "%s\n" "#define HAVE_NO_FINDEX_ENUMS 1" >>confdefs.h

fi

# See if the compiler supports intrinsics.

{ 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 (void)
{

  __cpuidex(0,0,0);

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
  tcl_cv_intrinsics=yes
else case e in #(
  e) tcl_cv_intrinsics=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
    conftest$ac_exeext conftest.$ac_ext
 ;;
esac
fi
{ 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

printf "%s\n" "#define HAVE_INTRIN_H 1" >>confdefs.h

fi

# See if the <wspiapi.h> header file is present

{ 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 (void)
{

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_wspiapi_h=yes
else case e in #(
  e) tcl_cv_wspiapi_h=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_wspiapi_h" >&5
printf "%s\n" "$tcl_cv_wspiapi_h" >&6; }
if test "$tcl_cv_wspiapi_h" = "yes"; then

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.

{ 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 (void)
{

  FINDEX_INFO_LEVELS i;
  FINDEX_SEARCH_OPS j;

  ;
  return 0;
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"
then :
  tcl_cv_findex_enums=yes
else case e in #(
  e) tcl_cv_findex_enums=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_findex_enums" >&5
printf "%s\n" "$tcl_cv_findex_enums" >&6; }
if test "$tcl_cv_findex_enums" = "no"; then

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.
#--------------------------------------------------------------------


    { 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+y}
then :
  enableval=$enable_symbols; tcl_ok=$enableval
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)'

printf "%s\n" "#define NDEBUG 1" >>confdefs.h

	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
printf "%s\n" "no" >&6; }

	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
	    { 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

printf "%s\n" "#define TCL_MEM_DEBUG 1" >>confdefs.h

    fi

    if test "$tcl_ok" = "compile" -o "$tcl_ok" = "all"; then

printf "%s\n" "#define TCL_COMPILE_DEBUG 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
	    { 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
	    { 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


    { 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+y}
then :
  enableval=$enable_embedded_manifest; embed_ok=$enableval
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_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 \[email protected] ; then mt.exe -nologo -manifest \[email protected]  -outputresource:\$@\;2 ; fi"
	VC_MANIFEST_EMBED_EXE="if test -f \[email protected] ; then mt.exe -nologo -manifest \[email protected]  -outputresource:\$@\;1 ; fi"
	result=yes
	if test "x" != x ; then
	    result="yes ()"
	fi

fi
rm -rf conftest*

    fi
    { 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${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 -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)` ${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}"


CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}
CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_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"
else
    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|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








# empty on win, but needs sub'ing










# win only















ac_config_files="$ac_config_files Makefile tclConfig.sh tcl.hpj 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
# 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}'







<
<
<
<
<
<
<
<




















|











|
|















|
|












|






|









|






|
|













|
|







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



















# win only















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
# 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_*) { 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
      # 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+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
      { 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
    { 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
: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.







|
<
<



















|















|
|







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
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=`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"
{ 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
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.







|
>






|
|




>




>
>
>
>
>
>
>
>



<
<
<
<
<
<
<
<
|
|
<
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
>
>
|
<
<
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>


|








<
<
<
<
<
<
<








>
|
>
>
>
|





|





|



<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












|

|







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 ${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 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








IFS=" ""	$as_nl"


PS1='$ '
PS2='> '






PS4='+ '








# Ensure predictable behavior from utilities with locale-dependent output.
LC_ALL=C
export LC_ALL


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 ${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









# 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 #(((
    '') 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'
# 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
  printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
  exit 1
fi























# 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
    printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
  fi
  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
# ---------------
# 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







>






|
>




|
|


|
>







|
>




|
|


|
>







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 :
  eval 'as_fn_append ()
  {
    eval $1+=\$2
  }'
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 :
  eval 'as_fn_arith ()
  {
    as_val=$(( $* ))
  }'
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
  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







|







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 ||
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
# 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







>
>
>
>












>
>
>
>
>
>












|
|
|







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'.
    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
  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







|








|







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=`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 ||
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
{
  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 $@








|
>


|
>














|
|







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_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_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.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
# 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







|







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
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

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







>
>

|

|
|


|







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='$ac_cs_config_escaped'
ac_cs_version="\\
tcl config.status 9.0
configured by $0, generated by GNU Autoconf 2.72,
  with options \\"\$ac_cs_config\\"

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
  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" ;;
    "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;;
  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







|

|





|





|





|
|




















|













|














<


|









|







|







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 )
    printf "%s\n" "$ac_cs_version"; exit ;;
  --config | --confi | --conf | --con | --co | --c )
    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=`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 )
    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_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
  \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
  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" ;;

    "tclsh.exe.manifest") CONFIG_FILES="$CONFIG_FILES tclsh.exe.manifest" ;;

  *) 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+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'.
$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
  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.







|







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'.
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
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







|







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;;
  :[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
    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







|





|

|



|



|



|
|




|
















|







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 ':'.
	 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=`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
    # use $as_me), people would be surprised to read:
    #    /* config.h.  Generated by config.status.  */
    configure_input='Generated from '`
	  printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
	`' by configure.'
    if test x"$ac_file" != x-; then
      configure_input="$ac_file.  $configure_input"
      { 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=`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 ||
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
	  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







|

|







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=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
  # A ".." for each directory in $ac_dir_suffix.
  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
/@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







|
|












|







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@*)
  { 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' = '.'.
# 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
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 \







|

|







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"; } &&
  { 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
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

  $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










|
|



>
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
  { 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
#! /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(../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"
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






>
|
|









|







1
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_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="b2"
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
# 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.







<







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_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

AS_IF([test "${enable_shared+set}" = "set"], [
  enableval="$enable_shared"
  tcl_ok=$enableval
], [
  tcl_ok=yes
])


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 "$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])

    ])
  ], [
    AC_SUBST(ZLIB_LIBS,[\${ZLIB_DIR_NATIVE}/win32/zdll.lib])
    AC_SUBST(TOMMATH_LIBS,[\${TOMMATH_DIR_NATIVE}/win32/tommath.lib])
  ])
], [
  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_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
])


#--------------------------------------------------------------------
#	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_PROG_TCLSH
    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)







>
>






>
|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
|
|
>










|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|

<




|













|










<
<


<
<

>







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163














164












165

166
167

168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
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-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_SUBST(ZLIB_OBJS,[\${ZLIB_OBJS}])
  AC_SUBST(TOMMATH_OBJS,[\${TOMMATH_OBJS}])
])
AC_DEFINE(HAVE_ZLIB, 1, [Is there an installed zlib?])
AC_SUBST(TCL_ZLIB_LIB_NAME, $zlib_lib_name)
AC_SUBST(TCL_TOMMATH_LIB_NAME, $tommath_lib_name)














AC_CHECK_TYPES([intptr_t, uintptr_t],,,[[












#include <stdint.h>

]])


#--------------------------------------------------------------------
#	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" ; 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
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
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

# 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([
#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)
)
if test "$tcl_cv_findex_enums" = "no"; then
    AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1,
            [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([
#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)
)
if test "$tcl_cv_intrinsics" = "yes"; then
    AC_DEFINE(HAVE_INTRIN_H, 1,
            [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([
#include <wspiapi.h>
], [],
        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])
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([
#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)
)
if test "$tcl_cv_findex_enums" = "no"; then
    AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1,
            [Defined when enums are missing from winbase.h])
fi

#--------------------------------------------------------------------







|



|
<


|
|
|










|




|
<

|
|
|










|

|
|
|












|



|
<


|
|
|







215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283

284
285
286
287
288
289
290
291
292
293
294
295

# 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_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])
)
if test "$tcl_cv_findex_enums" = "no"; then
    AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1,
            [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_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])
)
if test "$tcl_cv_intrinsics" = "yes"; then
    AC_DEFINE(HAVE_INTRIN_H, 1,
            [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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <wspiapi.h>
]], [[]])],
    [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])
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_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])
)
if test "$tcl_cv_findex_enums" = "no"; then
    AC_DEFINE(HAVE_NO_FINDEX_ENUMS, 1,
            [Defined when enums are missing from winbase.h])
fi

#--------------------------------------------------------------------
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
# 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_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

 eval "TCL_LIB_FILE=\"${LIBPREFIX}tcl${VER}${LIBSUFFIX}\""
else

 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}\""

# 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}"
else
    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
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)







|
|





|
>


>


|
|






<



<




















|

|












|







316
317
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${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 -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)` ${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}"


CFG_TCL_SHARED_LIB_SUFFIX=${TCL_SHARED_LIB_SUFFIX}
CFG_TCL_UNSHARED_LIB_SUFFIX=${TCL_UNSHARED_LIB_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"
else
    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|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
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)







<







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)


# 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
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)


dnl Local Variables:
dnl mode: autoconf;
dnl End:







<

<
<
<
<
<
<
<


















|
>


|

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)


AC_SUBST(TCL_BUILD_LIB_SPEC)







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_CONFIG_FILES([Makefile tclConfig.sh tclsh.exe.manifest])
AC_OUTPUT

dnl Local Variables:
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
# 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.
#
# Possible values of TARGET are:

#	release  -- Builds the core, the shell and the dlls. (default)

#	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).







|
|

|
>
|
>
|
<
<







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/main/tip/477.md)
# or examine Sections 7-9 in rules.vc.
#
# 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.


#	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
# 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.
#
# 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
#		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.
#





#		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
#			    support.

#		nothreads = Turns off full multithreading support (default on).
#		pbds      =  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.
#		staticpkg = Affects the static option only to switch
#			    tclshXX.exe to have the dde and reg extension linked
#			    inside it.
#		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







|
|
|


|




>
>
>
>
>
|
|
|

>

|
|

|
<
|
<
|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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.
#
# Basic macros and options usable on the commandline (see rules.vc for more info):
#	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).
#		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).
#		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), and

#			    have the dde and registry extensions linked inside.

#		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
#
#		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)
#		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.
#
#	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







|











|







93
94
95
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|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 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
# 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.
RCFILE = tcl.rc

# The rules.vc file does most of the hard work in terms of defining
# the build configuration, macros, output directories etc.
!include "rules.vc"








# 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)
























# 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]







|


|



>
>
>
>
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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 have a custom resource file
RCFILE = tcl.rc

# 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
!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]
!endif

!include versions.vc

DDEDOTVERSION = 1.4
DDEVERSION = $(DDEDOTVERSION:.=)

REGDOTVERSION = 1.3
REGVERSION = $(REGDOTVERSION:.=)

TCLREGLIBNAME	= $(PROJECT)reg$(REGVERSION)$(SUFX:t=).$(EXT)
TCLREGLIB	= $(OUT_DIR)\$(TCLREGLIBNAME)

TCLDDELIBNAME	= $(PROJECT)dde$(DDEVERSION)$(SUFX:t=).$(EXT)
TCLDDELIB	= $(OUT_DIR)\$(TCLDDELIBNAME)

TCLTEST		= $(OUT_DIR)\$(PROJECT)test.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 \

!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


COREOBJS = \
	$(TMP_DIR)\regcomp.obj \
	$(TMP_DIR)\regerror.obj \
	$(TMP_DIR)\regexec.obj \
	$(TMP_DIR)\regfree.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)\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 \







|










|


|


|
>



<
<
<
<
<
<








>

<
<
<
<


|
>






>







>







200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228






229
230
231
232
233
234
235
236
237
238




239
240
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\registry\pkgIndex.tcl "registry " >> versions.vc]
!endif

!include versions.vc

DDEDOTVERSION = 1.4
DDEVERSION = $(DDEDOTVERSION:.=)

REGDOTVERSION = 1.3
REGVERSION = $(REGDOTVERSION:.=)

TCLREGLIBNAME	= $(PROJECT)9registry$(REGVERSION)$(SUFX:t=).$(EXT)
TCLREGLIB	= $(OUT_DIR)\$(TCLREGLIBNAME)

TCLDDELIBNAME	= $(PROJECT)9dde$(DDEVERSION)$(SUFX:t=).$(EXT)
TCLDDELIB	= $(OUT_DIR)\$(TCLDDELIBNAME)

TCLTEST		= $(OUT_DIR)\$(PROJECT)test$(VERSION)$(SUFX:t=).exe
TCLTESTRAW	= $(TCLTEST:.exe=-raw.exe)

TCLSHOBJS = \
	$(TMP_DIR)\tclAppInit.obj \






	$(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)




	$(OUT_DIR)\tommath.lib \
!endif
	$(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 \
285
286
287
288
289
290
291

292
293
294
295
296
297
298
	$(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)\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 \







>







314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
	$(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
	$(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_mp_exch.obj \
	$(TMP_DIR)\bn_mp_expt_u32.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_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_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 \







|

|


















>
>















>







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
	$(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_s_mp_div_3.obj \
	$(TMP_DIR)\bn_mp_exch.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
	$(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)\tclWinReg.obj \
	$(TMP_DIR)\tclWinDde.obj \
!else
	$(TMP_DIR)\tcl.res
!endif

TCLOBJS = $(COREOBJS) $(ZLIBOBJS) $(TOMMATHOBJS) $(PLATFORMOBJS)

TCLSTUBOBJS = \
	$(TMP_DIR)\tclStubLib.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



# 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

# 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

























#---------------------------------------------------------------------

release:    setup $(TCLSH) $(TCLSTUBLIB) dlls pkgs


core:	    setup $(TCLLIB) $(TCLSTUBLIB)





shell:	    setup $(TCLSH)





dlls:	    setup $(TCLREGLIB) $(TCLDDELIB) $(OUT_DIR)\zlib1.dll $(OUT_DIR)\libtommath.dll

all:	    setup $(TCLSH) $(TCLSTUBLIB) dlls pkgs
tcltest:    setup $(TCLTEST) dlls





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
	$(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]
<<

runtest: setup $(TCLTEST) dlls
	set TCL_LIBRARY=$(ROOT:\=/)/library
	$(DEBUGGER) $(TCLTEST) $(SCRIPT)

runshell: setup $(TCLSH) dlls
	set TCL_LIBRARY=$(ROOT:\=/)/library
	$(DEBUGGER) $(TCLSH) $(SCRIPT)

!if $(STATIC_BUILD)

$(TCLLIB): $(TCLOBJS)
	$(LIBCMD) @<<
$**
<<

!else

$(TCLLIB): $(TCLOBJS)
	$(DLLCMD) @<<
$**
<<
	$(_VC_MANIFEST_EMBED_DLL)




$(TCLIMPLIB): $(TCLLIB)

!endif # $(STATIC_BUILD)

$(TCLSTUBLIB): $(TCLSTUBOBJS)
	$(LIBCMD) -nodefaultlib $(TCLSTUBOBJS)

$(TCLSH): $(TCLSHOBJS) $(TCLSTUBLIB) $(TCLIMPLIB)
	$(CONEXECMD) -stack:2300000 $**

	$(_VC_MANIFEST_EMBED_EXE)





$(TCLTEST): $(TCLTESTOBJS) $(TCLSTUBLIB) $(TCLIMPLIB)
	$(CONEXECMD) -stack:2300000 $**

	$(_VC_MANIFEST_EMBED_EXE)




!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
$(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









!endif






















pkgs:
	@for /d %d in ($(PKGSDIR)\*) do \
	  @if exist "%~fd\win\makefile.vc" ( \
	    pushd "%~fd\win" & \
	    $(MAKE) -$(MAKEFLAGS) -f makefile.vc TCLDIR=$(ROOT) &\
	    popd \







>










>
>








>
>




















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
>
>
|
>
>
>
>
>
|
>
>
>
>
>

>
|
|
>
>
>
>
>







|
|

|
|



|


|
|
















>
>
>










>

>
>
>
>



>

>
>
>



















|
|
|
|
|
|
|
|
|
|








>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
	$(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

LIBTCLVFS = $(OUT_DIR)\libtcl.vfs

# 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

# 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 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)

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: tcltest
	set TCL_LIBRARY=$(TCL_TEST_LIBRARY)
	$(DEBUGGER) $(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile <<
		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=$(TCL_TEST_LIBRARY)
	$(DEBUGGER) $(TCLTEST) $(SCRIPT)

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)" == "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
!if $(STATIC_BUILD)
# 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"
!else
    @$(COPY) $(TCLDDELIB) "$(LIBTCLVFS)\tcl_library\dde
    @$(COPY) $(TCLREGLIB) "$(LIBTCLVFS)\tcl_library\registry
!endif
	@echo file delete -force {$@} > "$(OUT_DIR)\zipper.tcl"
	@echo zipfs mkzip {$@} {$(LIBTCLVFS)} {$(LIBTCLVFS)} >> "$(OUT_DIR)\zipper.tcl"
	@cd "$(OUT_DIR)" && $(TCLSH_NATIVE) 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 \
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
!else
	$(TCLSH) $(TOOLSDIR:\=/)/genStubs.tcl $(GENERICDIR:\=/) \
		$(GENERICDIR:\=/)/tcl.decls $(GENERICDIR:\=/)/tclInt.decls \
		$(GENERICDIR:\=/)/tclTomMath.decls
	$(TCLSH) $(TOOLSDIR:\=/)/genStubs.tcl $(GENERICDIR:\=/) \
		$(GENERICDIR:\=/)/tclOO.decls
!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.







<







710
711
712
713
714
715
716

717
718
719
720
721
722
723
!else
	$(TCLSH) $(TOOLSDIR:\=/)/genStubs.tcl $(GENERICDIR:\=/) \
		$(GENERICDIR:\=/)/tcl.decls $(GENERICDIR:\=/)/tclInt.decls \
		$(GENERICDIR:\=/)/tclTomMath.decls
	$(TCLSH) $(TOOLSDIR:\=/)/genStubs.tcl $(GENERICDIR:\=/) \
		$(GENERICDIR:\=/)/tclOO.decls
!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.
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
@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_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_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


<<


#---------------------------------------------------------------------
# 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.







<











<

<
<


|
|


<

|






<







>
>







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
@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

@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

@LDFLAGS@


@LIBOBJS@
@RANLIB@
@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_SRC_DIR@        $(ROOT)
@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_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

#---------------------------------------------------------------------
# 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$@ $?












$(TMP_DIR)\tclTest.obj: $(GENERICDIR)\tclTest.c
	$(cc32) $(appcflags) -Fo$@ $?


$(TMP_DIR)\tclTestObj.obj: $(GENERICDIR)\tclTestObj.c
	$(cc32) $(appcflags) -Fo$@ $?




$(TMP_DIR)\tclWinTest.obj: $(WIN_DIR)\tclWinTest.c
	$(CCAPPCMD) $?

$(TMP_DIR)\tclZipfs.obj: $(GENERICDIR)\tclZipfs.c

	$(cc32) $(pkgcflags) -I$(COMPATDIR)\zlib -I$(COMPATDIR)\zlib\contrib\minizip -Fo$@ $?


$(TMP_DIR)\tclZlib.obj: $(GENERICDIR)\tclZlib.c
	$(cc32) $(pkgcflags) -I$(COMPATDIR)\zlib -Fo$@ $?














$(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_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$@ $?


$(TMP_DIR)\tclWinDde.obj: $(WIN_DIR)\tclWinDde.c
	$(cc32) $(appcflags) /DUSE_TCL_STUBS -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)\tclTomMathStubLib.obj: $(GENERICDIR)\tclTomMathStubLib.c
	$(cc32) $(stubscflags) -Fo$@ $?

$(TMP_DIR)\tclOOStubLib.obj: $(GENERICDIR)\tclOOStubLib.c
	$(cc32) $(stubscflags) -Fo$@ $?








<






>
>
>
>
>
>
>
>
>
>
>
|
|
>



>
>
>





>
|
>




>
>
>
>
>
>
>
>
>
>
>
>
>












|
<




<





|



|








>
>
>
>
>
>
>
>
>







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

#---------------------------------------------------------------------
# Special case object file targets
#---------------------------------------------------------------------

$(TMP_DIR)\testMain.obj: $(WIN_DIR)\tclAppInit.c
	$(cc32) $(appcflags) /DTCL_TEST /DUNICODE /D_UNICODE \

	    -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$(TMP_DIR) \
	    -Fo$@ $(GENERICDIR)\tclEvent.c

$(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) \
	-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="\"$(TCL_LIB_FILE)\""     \

	-Fo$@ $?

$(TMP_DIR)\tclAppInit.obj: $(WIN_DIR)\tclAppInit.c
	$(cc32) $(appcflags) /DUNICODE /D_UNICODE \

	    -Fo$@ $?

### The following objects should be built using the stub interfaces

$(TMP_DIR)\tclWinReg.obj: $(WIN_DIR)\tclWinReg.c
	$(cc32) $(appcflags_nostubs) /DUSE_TCL_STUBS=1 -Fo$@ $?


$(TMP_DIR)\tclWinDde.obj: $(WIN_DIR)\tclWinDde.c
	$(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
{$(COMPATDIR)\zlib}.c{$(TMP_DIR)}.obj::
	$(cc32) $(pkgcflags) -Fo$(TMP_DIR)\ @<<
$<
<<

$(TMP_DIR)\tclsh.res: $(TMP_DIR)\tclsh.exe.manifest $(WIN_DIR)\tclsh.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 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 "$(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)\"

	@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)\"
	@$(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)\"

	@$(CPY) "$(OUT_DIR)\tclConfig.sh"         "$(LIB_INSTALL_DIR)\"
	@$(CPY) "$(WIN_DIR)\tclooConfig.sh"        "$(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) "$(OUT_DIR)\tcl.nmake"            "$(LIB_INSTALL_DIR)\nmake\"

	@echo Installing package cookiejar $(PKG_COOKIEJAR_VER)


	@$(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)


	@$(CPY) "$(ROOT)\library\opt\*.tcl" \
	    "$(SCRIPT_INSTALL_DIR)\opt0.4\"


	@echo Installing package http $(PKG_HTTP_VER) as a Tcl Module


	@$(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


	@$(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
	@$(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

	@echo Installing encodings
	@$(CPY) "$(ROOT)\library\encoding\*.enc" \
		"$(SCRIPT_INSTALL_DIR)\encoding\"

# "emacs font-lock highlighting fix

install-tzdata:

	@echo Installing time zone data
	@set TCL_LIBRARY=$(ROOT:\=/)/library
	@$(TCLSH_NATIVE) "$(ROOT:\=/)/tools/installData.tcl" \
	    "$(ROOT:\=/)/library/tzdata" "$(SCRIPT_INSTALL_DIR)/tzdata"


install-msgs:

	@echo Installing message catalogs
	@set TCL_LIBRARY=$(ROOT:\=/)/library
	@$(TCLSH_NATIVE) "$(ROOT:\=/)/tools/installData.tcl" \
	    "$(ROOT:\=/)/library/msgs" "$(SCRIPT_INSTALL_DIR)/msgs"


install-pdbs:
	@echo Installing debug symbols
	@$(CPY) "$(OUT_DIR)\*.pdb" "$(BIN_INSTALL_DIR)\"
# "emacs font-lock highlighting fix

#---------------------------------------------------------------------







>














>
>
>
>








|
|
<
<
<
<
<
<
<
<
<
<









>

>
>










>


>



>

>

>
>





>
>


>
>

>
>









>
>





>

|
<
<
<
<





|
<
<
<
<
|
|
|

>



>



>




>


>




>







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
{$(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 "$(LIB_INSTALL_DIR)\nmake" \
		$(MKDIR) "$(LIB_INSTALL_DIR)\nmake"










	@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)
	@if not exist "$(SCRIPT_INSTALL_DIR)" \
	    $(MKDIR) "$(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)\"
	@$(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"
!endif
	@echo Installing $(TCLDDELIBNAME)
!if !$(STATIC_BUILD)




	@$(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)




	@$(CPY) "$(TCLREGLIB)" "$(LIB_INSTALL_DIR)\registry$(REGDOTVERSION)\"
	@$(CPY) "$(ROOT)\library\registry\pkgIndex.tcl" \
	    "$(LIB_INSTALL_DIR)\registry$(REGDOTVERSION)\"
!endif
!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

#---------------------------------------------------------------------
1014
1015
1016
1017
1018
1019
1020

1021
1022
1023
1024
	@if exist $(TCLDDELIB) del $(TCLDDELIB)
	@echo Removing $(TCLREGLIB) ...
	@if exist $(TCLREGLIB) del $(TCLREGLIB)

clean: default-clean clean-pkgs
hose: default-hose
realclean: hose


# Local Variables:
# mode: makefile
# End:







>




1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
	@if exist $(TCLDDELIB) del $(TCLDDELIB)
	@echo Removing $(TCLREGLIB) ...
	@if exist $(TCLREGLIB) del $(TCLREGLIB)

clean: default-clean clean-pkgs
hose: default-hose
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
/*
 * ----------------------------------------------------------------------------
 * 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
 *
 * 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>

#pragma comment (lib, "user32.lib")
#pragma comment (lib, "kernel32.lib")

#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
#define   snprintf	_snprintf
#endif


/* protos */

static int CheckForCompilerFeature(const char *option);
static int CheckForLinkerFeature(const 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'};

/*
 * exitcodes: 0 == no, 1 == yes, 2 == error
 */

int
main(






|
|








>


>

<











|







|
















|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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 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>


/*
 * 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++ */
#if defined(_WIN32) && defined(_MSC_VER) && _MSC_VER < 1900
#define   snprintf	_snprintf
#endif


/* protos */

static int CheckForCompilerFeature(const char *option);
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, ""};
pipeinfo Err = {INVALID_HANDLE_VALUE, ""};

/*
 * exitcodes: 0 == no, 1 == yes, 2 == error
 */

int
main(
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
    char msg[300];
    BOOL ok;
    HANDLE hProcess, h, pipeThreads[2];
    char cmdline[100];

    hProcess = GetCurrentProcess();

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
    si.hStdInput = INVALID_HANDLE_VALUE;

    ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = FALSE;

    /*
     * Create a non-inheritible pipe.
     */

    CreatePipe(&Out.pipe, &h, &sa, 0);

    /*
     * Dupe the write side, make it inheritible, 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.







|
|




|





|





|







202
203
204
205
206
207
208
209
210
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();

    memset(&pi, 0, sizeof(PROCESS_INFORMATION));
    memset(&si, 0, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
    si.hStdInput = INVALID_HANDLE_VALUE;

    memset(&sa, 0, sizeof(SECURITY_ATTRIBUTES));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = NULL;
    sa.bInheritHandle = FALSE;

    /*
     * Create a non-inheritable pipe.
     */

    CreatePipe(&Out.pipe, &h, &sa, 0);

    /*
     * 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.
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
	    NULL,	    /* Use parent's starting directory. */
	    &si,	    /* Pointer to STARTUPINFO structure. */
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */

    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],
		(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.







|


|







267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
	    NULL,	    /* Use parent's starting directory. */
	    &si,	    /* Pointer to STARTUPINFO structure. */
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */

    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%lu]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		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.
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
             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
}

static int
CheckForLinkerFeature(
    const 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));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
    si.hStdInput = INVALID_HANDLE_VALUE;

    ZeroMemory(&sa, 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.
     */

    DuplicateHandle(hProcess, h, hProcess, &si.hStdOutput, 0, TRUE,
	    DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

    /*
     * Same as above, but for the error side.







|














|
|




|











|







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
             || strstr(Err.buffer, "D9002") != NULL
             || strstr(Out.buffer, "D2021") != NULL
             || strstr(Err.buffer, "D2021") != NULL);
}

static int
CheckForLinkerFeature(
    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();

    memset(&pi, 0, sizeof(PROCESS_INFORMATION));
    memset(&si, 0, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags   = STARTF_USESTDHANDLES;
    si.hStdInput = INVALID_HANDLE_VALUE;

    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 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.
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
	    NULL,	    /* Use parent's starting directory. */
	    &si,	    /* Pointer to STARTUPINFO structure. */
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */

    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],
		(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.







|


|







401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
	    NULL,	    /* Use parent's starting directory. */
	    &si,	    /* Pointer to STARTUPINFO structure. */
	    &pi);	    /* Pointer to PROCESS_INFORMATION structure. */

    if (!ok) {
	DWORD err = GetLastError();
	int chars = snprintf(msg, sizeof(msg) - 1,
		"Tried to launch: \"%s\", but got error [%lu]: ", cmdline, err);

	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|
		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.
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

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) {
	    LPSTR p, q;

	    p = strstr(szBuffer, match);
	    if (p != NULL) {
		/*
		 * Skip to first digit after the match.
		 */

		p += strlen(match);
		while (*p && !isdigit(*p)) {
		    ++p;
		}

		/*
		 * Find ending whitespace.
		 */

		q = p;
		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;
		break;
	    }
	}
	fclose(fp);
    }
    return szResult;
}







<









|









|








|
|



<
|
|







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

static const char *
GetVersionFromFile(
    const char *filename,
    const char *match,
    int numdots)
{

    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, 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((unsigned char)*p)) {
		    ++p;
		}

		/*
		 * Find ending whitespace.
		 */

		q = p;
		while (*q && (strchr("0123456789.ab", *q)) && (((!strchr(".ab", *q)
			    && !strchr("ab", q[-1])) || --numdots))) {
		    ++q;
		}


		*q = 0;
		szResult = p;
		break;
	    }
	}
	fclose(fp);
    }
    return szResult;
}
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
    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));
    if (itemPtr) {
	itemPtr->key = strdup(key);
	itemPtr->value = strdup(value);
	itemPtr->nextPtr = NULL;

	while(*listPtrPtr) {
	    listPtrPtr = &(*listPtrPtr)->nextPtr;







|







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 = (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
    }
}

/*
 * 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
 *	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)
 *        <<
 */

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
	 */

	sp = fopen(substitutions, "rt");
	if (sp != NULL) {
	    while (fgets(szBuffer, cbBuffer, 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;







|

















<

<







|




|







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 -
 *	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)
 *        <<
 */

static int
SubstituteFile(
    const char *substitutions,
    const char *filename)
{

    static char szBuffer[1024], szCopy[1024];

    list_item_t *substPtr = NULL;
    FILE *fp, *sp;

    fp = fopen(filename, "rt");
    if (fp != NULL) {

	/*
	 * Build a list of substitutions from the first filename
	 */

	sp = fopen(substitutions, "rt");
	if (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
	}
#endif

	/*
	 * Run the substitutions over each line of the input
	 */

	while (fgets(szBuffer, cbBuffer, 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);
	}

	list_free(&substPtr);
    }
    fclose(fp);
    return 0;
}







|
















|







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, 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("%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
 * 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];

    int dirlen, keylen, ret;
    WIN32_FIND_DATA finfo;

    if (dir == NULL || keypath == NULL)
	return 2; /* Have no real error reporting mechanism into nmake */

    dirlen = strlen(dir);
    if ((dirlen + 3) > sizeof(path))
	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,







>
|


|

>

|

>







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
 * 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 keylen, ret;
    WIN32_FIND_DATA finfo;

    if (dir == NULL || keypath == NULL) {
	return 2; /* Have no real error reporting mechanism into nmake */
    }
    dirlen = strlen(dir);
    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,
788
789
790
791
792
793
794

795
796
797
798
799
800
801

802
803
804
805
806
807
808
 *      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)
{

    int i, ret;
    static const char *paths[] = {"..", "..\\..", "..\\..\\.."};

    for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
	ret = LocateDependencyHelper(paths[i], keypath);
	if (ret == 0)
	    return ret;

    }
    return ret;
}


/*
 * Local variables:







>
|




|

>







788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
 *      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 ret;
    static const char *paths[] = {"..", "..\\..", "..\\..\\.."};

    for (i = 0; i < (sizeof(paths)/sizeof(paths[0])); ++i) {
	ret = LocateDependencyHelper(paths[i], keypath);
	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
!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 [$(CC) -nologo "nmakehlp.c" -link -subsystem:console > nul]




!endif

# First locate the Tcl directory that we are working with.
!if "$(TCLDIR)" != ""

_RULESDIR = $(TCLDIR:/=\)








>
|
>
>
>
>







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 -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
#------------------------------------------------------------- -*- 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
# 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

# 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)" == ""








|

















|







1
2
3
4
5
6
7
8
9
10
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/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 = 11

# 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
# 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. 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
# 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.







>
>
|
|
|
<







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
# 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

# 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
# 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
# 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.







|
|







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, 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
_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)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







>
>







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

#----------------------------------------------------------------
# The MACHINE macro is used by legacy makefiles so set it as well
!ifdef MACHINE
!if "$(MACHINE)" == "x86"
!undef MACHINE
MACHINE = IX86



!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


!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


!else
NATIVE_ARCH=AMD64
!endif

# Since MSVC8 we must deal with manifest resources.
!if $(VCVERSION) >= 1400
_VC_MANIFEST_EMBED_EXE=if exist [email protected] mt -nologo -manifest [email protected] -outputresource:$@;1







>
>
>
















>
>















>
>







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 [email protected] mt -nologo -manifest [email protected] -outputresource:$@;1
537
538
539
540
541
542
543

544
545




546
547
548
549
550
551
552
!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 [$(cc32) -nologo "$(NMAKEHLPC)" -link -subsystem:console > nul]
!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:







>


>
>
>
>







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
# 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. 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)

# 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.
# 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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|













>

|
|









<
<







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

########################################################################
# 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 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)


# 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
!if [nmakehlp -f $(OPTS) "nomsvcrt"]
!message *** Doing nomsvcrt
MSVCRT		= 0
!else
!if [nmakehlp -f $(OPTS) "msvcrt"]
!message *** Doing msvcrt
!else
!if $(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 "$(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







|
















>
>
>
>
>
|




<
<
<
<
<







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
!if [nmakehlp -f $(OPTS) "nomsvcrt"]
!message *** Doing nomsvcrt
MSVCRT		= 0
!else
!if [nmakehlp -f $(OPTS) "msvcrt"]
!message *** Doing msvcrt
!else
!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 $(TCL_MAJOR_VERSION) == 8
!if [nmakehlp -f $(OPTS) "time64bit"]
!message *** Force 64-bit time_t
_USE_64BIT_TIME_T = 1
!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
MSG=^
This compiler does not support profile guided optimization.
!error $(MSG)
!endif
!endif

################################################################
# 7. 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







|







968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
MSG=^
This compiler does not support profile guided optimization.
!error $(MSG)
!endif
!endif

################################################################
# 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
!else
TCL_COMPILE_DEBUG   = 0
!endif

!endif

####################################################################
# 8. 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







|







998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
!else
TCL_COMPILE_DEBUG   = 0
!endif

!endif

####################################################################
# 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
!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.,
#







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1030
1031
1032
1033
1034
1035
1036





























































































1037
1038
1039
1040
1041
1042
1043
!if [nmakehlp -f $(CHECKS) "64bit"] && [nmakehlp -c -Wp64]
!message *** Doing 64bit portability warnings
WARNINGS		    = $(WARNINGS) -Wp64
!endif

!endif































































































################################################################
# 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
SUFX	    = $(SUFX:s=)
EXT	    = dll
TMP_DIRFULL = $(TMP_DIRFULL:X=)
SUFX	    = $(SUFX:x=)
!else
TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=)
EXT	    = lib
!if !$(MSVCRT)
TMP_DIRFULL = $(TMP_DIRFULL:X=)
SUFX	    = $(SUFX:x=)
!endif
!endif

!if !$(TCL_THREADS) || $(TCL_VERSION) > 86
TMP_DIRFULL = $(TMP_DIRFULL:Threaded=)







|







1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
SUFX	    = $(SUFX:s=)
EXT	    = dll
TMP_DIRFULL = $(TMP_DIRFULL:X=)
SUFX	    = $(SUFX:x=)
!else
TMP_DIRFULL = $(TMP_DIRFULL:Dynamic=)
EXT	    = lib
!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
!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)





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)



TCLSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib



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


TCLSTUBLIB	= $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib



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

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

TCLSTUBLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib



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

TCLTOOLSDIR	= $(_TCLDIR)\tools
TCL_INCLUDES	= -I"$(_TCLDIR)\generic" -I"$(_TCLDIR)\win"

!endif # TCLINSTALL




tcllibs = "$(TCLSTUBLIB)" "$(TCLIMPLIB)"


!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)









TKSTUBLIBNAME	= tkstub$(TK_VERSION).lib

TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX).lib


!if $(DOING_TK)
WISH 		= $(OUT_DIR)\$(WISHNAME)
TKSTUBLIB	= $(OUT_DIR)\$(TKSTUBLIBNAME)
TKIMPLIB	= $(OUT_DIR)\$(TKIMPLIBNAME)
TKLIB		= $(OUT_DIR)\$(TKLIBNAME)
TK_INCLUDES    = -I"$(WIN_DIR)" -I"$(GENERICDIR)"


!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"


!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"


!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)






PRJLIB		= $(OUT_DIR)\$(PRJLIBNAME)


PRJSTUBLIBNAME	= $(STUBPREFIX)$(VERSION).lib



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)







>

>
|
>
>
>

>





>

>

>
>
>















>

>
>
>









>









>

>
>
>









>





>
>
>

>

















|
>
>
>
>
>
>
>
>
>

>
|
>






|
>














>
>

>










>
>

>







|
>
>
>
>
>
>


>

>
>
>







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
!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
#

# TIP 430. Unused for 8.6 but no harm defining it to allow a common rules.vc
TCLSCRIPTZIPNAME = libtcl$(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)$(TCL_PATCH_LETTER)$(TCL_RELEASE_SERIAL).zip
TKSCRIPTZIPNAME = 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)\$(TCLSCRIPTZIPNAME)

!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\$(TCLSCRIPTZIPNAME)
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)\$(TCLSCRIPTZIPNAME)
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
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
TKSTUBLIBNAME	= tkstub.lib
!endif

!if $(DOING_TK)
WISH 		= $(OUT_DIR)\$(WISHNAME)
TKSTUBLIB	= $(OUT_DIR)\$(TKSTUBLIBNAME)
TKIMPLIB	= $(OUT_DIR)\$(TKIMPLIBNAME)
TKLIB		= $(OUT_DIR)\$(TKLIBNAME)
TK_INCLUDES     = -I"$(WIN_DIR)" -I"$(GENERICDIR)"
TKSCRIPTZIP     = $(OUT_DIR)\$(TKSCRIPTZIPNAME)

!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\$(TKSCRIPTZIPNAME)

!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)\$(TKSCRIPTZIPNAME)

!endif # TKINSTALL

tklibs = "$(TKSTUBLIB)" "$(TKIMPLIB)"

!endif # $(DOING_TK)
!endif # $(DOING_TK) || $(NEED_TK)

# Various output paths
PRJIMPLIB	= $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
PRJLIBNAME8	= $(PROJECT)$(VERSION)$(SUFX).$(EXT)
PRJLIBNAME9	= tcl9$(PROJECT)$(VERSION)$(SUFX).$(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
# 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
# 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	= $(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







|












|
|







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
# 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 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 /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
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"
OPTDEFINES	= $(OPTDEFINES) /DMP_64BIT
!endif
!endif
!if $(TCL_NO_DEPRECATED)
OPTDEFINES	= $(OPTDEFINES) /DTCL_NO_DEPRECATED
!endif








|







1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
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" || "$(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
!if $(OPTIMIZING)
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_OPTIMIZED
!endif
!endif
!if $(PROFILE)
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_PROFILED
!endif
!if "$(MACHINE)" == "AMD64"
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_DO64BIT
!endif
!if $(VCVERSION) < 1300
OPTDEFINES	= $(OPTDEFINES) /DNO_STRTOI64=1
!endif

!if "$(TCL_MAJOR_VERSION)" == "8"
!if "$(_USE_64BIT_TIME_T)" == "1"
OPTDEFINES	= $(OPTDEFINES) /D_USE_64BIT_TIME_T=1
!endif
!if "$(TCL_UTF_MAX)" == "4"
OPTDEFINES	= $(OPTDEFINES) /DTCL_UTF_MAX=4
!endif

# _ATL_XP_TARGETING - Newer SDK's need this to build for XP
COMPILERFLAGS  = /D_ATL_XP_TARGETING
!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)\"" \







|






|



<
<
<




>
>
>







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
!if $(OPTIMIZING)
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_OPTIMIZED
!endif
!endif
!if $(PROFILE)
OPTDEFINES	= $(OPTDEFINES) /DTCL_CFG_PROFILED
!endif
!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 "$(_USE_64BIT_TIME_T)" == "1"
OPTDEFINES	= $(OPTDEFINES) /D_USE_64BIT_TIME_T=1
!endif




# _ATL_XP_TARGETING - Newer SDK's need this to build for XP
COMPILERFLAGS  = /D_ATL_XP_TARGETING
!endif
!if "$(TCL_BUILD_FOR)" == "8"
OPTDEFINES	= $(OPTDEFINES) /DTCL_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)\"" \
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
cdebug = $(OPTIMIZATIONS)
!if $(SYMBOLS)
cdebug = $(cdebug) -Zi
!endif

!endif # $(DEBUG)

# cwarn includes default warning levels.
cwarn = $(WARNINGS)

!if "$(MACHINE)" == "AMD64"
# 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






!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)





# 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








|
|

|














>
>
>
>
>

















>
>
>
>







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
cdebug = $(OPTIMIZATIONS)
!if $(SYMBOLS)
cdebug = $(cdebug) -Zi
!endif

!endif # $(DEBUG)

# cwarn includes default warning levels, also C4090 (buggy) and C4146 is useless.
cwarn = $(WARNINGS) -wd4090 -wd4146

!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
# 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)

# Link flags

!if $(DEBUG)
ldebug	= -debug -debugtype:cv
!else
ldebug	= -release -opt:ref -opt:icf,3







|







1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
# 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 /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
!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.







<
<
<
<
<
<
<
<
<
<
<
<







1580
1581
1582
1583
1584
1585
1586












1587
1588
1589
1590
1591
1592
1593
!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

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

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) \
	    /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 package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
	    [list load [file join $$dir $(PLATFORM_IDENTIFY) $(PRJLIBNAME)]] > $(OUT_DIR)\pkgIndex.tcl




!else
default-pkgindex:

	@echo package ifneeded $(PRJ_PACKAGE_TCLNAME) $(DOTVERSION) \
	    [list load [file join $$dir $(PRJLIBNAME)]] > $(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)


<<

default-install: default-install-binaries default-install-libraries
!if $(SYMBOLS)
default-install: default-install-pdbs
!endif








|
















>

|
>
>
>
>


>

|
>
>
>
>








>
>







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

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) /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) $(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 $(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
	@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)\"



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:







>
>







1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
	@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:
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
!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"
!endif
!endif # TCLINSTALL

!if $(CONFIG_CHECK)
!ifdef TCLNMAKECONFIG
!include $(TCLNMAKECONFIG)








|
|







1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
!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("$(_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
#------------------------------------------------------------- -*- 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.

$(PROJECT): setup pkgindex $(PRJLIB)

!ifdef PRJ_STUBOBJS
$(PROJECT): $(PRJSTUBLIB)
$(PRJSTUBLIB): $(PRJ_STUBOBJS)
	$(LIBCMD) $**






|







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/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

!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 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 Rebuild_Opt "clean release"
# PROP Target_File "Release\tclsh90t.exe"
# PROP Bsc_Name ""
# PROP Target_Dir ""

!ELSEIF  "$(CFG)" == "tcl - Win32 Debug"








|








|







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 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 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
!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







<
<
<
<
<
<
<
<












<
<
<
<
<
<
<
<




<
<
<
<


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







132
133
134
135
136
137
138








139
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\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\README
# End Source File
# Begin Source File





SOURCE=..\compat\string.h
# 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

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







<
<
<
<







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\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
# End Source File
# Begin Source File

SOURCE=..\doc\safe.n
# End Source File
# Begin Source File

SOURCE=..\doc\SaveResult.3
# End Source File
# Begin Source File

SOURCE=..\doc\scan.n
# End Source File
# Begin Source File








|







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\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
# End Source File
# Begin Source File

SOURCE=..\doc\SplitPath.3
# End Source File
# Begin Source File

SOURCE=..\doc\StaticPkg.3
# End Source File
# Begin Source File

SOURCE=..\doc\StdChannels.3
# End Source File
# Begin Source File








|







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\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
SOURCE=..\generic\tclStubInit.c
# End Source File
# Begin Source File

SOURCE=..\generic\tclStubLib.c
# End Source File
# Begin Source File









SOURCE=..\generic\tclOOStubLib.c
# End Source File
# Begin Source File

SOURCE=..\generic\tclTomMathStubLib.c
# End Source File







>
>
>
>
>
>
>
>







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

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







<
<
<
<







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.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
    # 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],
		[directory containing tcl configuration (tclConfig.sh)]),
	    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 )







|

|







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,
	    AS_HELP_STRING([--with-tcl],
		[directory containing tcl configuration (tclConfig.sh)]),
	    [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
    # 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],
		[directory containing tk configuration (tkConfig.sh)]),
	    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 )







|

|







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,
	    AS_HELP_STRING([--with-tk],
		[directory containing tk configuration (tkConfig.sh)]),
	    [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
#
# 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







<







247
248
249
250
251
252
253

254
255
256
257
258
259
260
#
# Results:
#
#	Substitutes the following vars:
#		TCL_BIN_DIR
#		TCL_SRC_DIR
#		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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
    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)







<







283
284
285
286
287
288
289

290
291
292
293
294
295
296
    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_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)
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
#------------------------------------------------------------------------

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?])







<
<
<
<
<
<
<
<







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 "$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
# Results:
#
#	Can the following vars:
#		EXTRA_CFLAGS
#		CFLAGS_DEBUG
#		CFLAGS_OPTIMIZE
#		CFLAGS_WARNING

#		LDFLAGS_DEBUG
#		LDFLAGS_OPTIMIZE
#		LDFLAGS_CONSOLE
#		LDFLAGS_WINDOW
#		CC_OBJNAME
#		CC_EXENAME
#		CYGPATH







>







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

    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.
    MACHINE="X86"

    if test "$GCC" = "yes"; then

      AC_CACHE_CHECK(for cross-compile version of gcc,
	ac_cv_cross,
	AC_TRY_COMPILE([
	    #ifndef _WIN32
		#error cross-compiler
	    #endif
	], [],
	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"
	    ;;







	    *)
		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"
	    ;;







|






|



|
|
|











>
>
>
>
>
>
>







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|arm64|ia64.
    MACHINE="X86"

    if test "$GCC" = "yes"; then

      AC_CACHE_CHECK(for cross-compile version of gcc,
	ac_cv_cross,
	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
	    #ifndef _WIN32
		#error cross-compiler
	    #endif
	]], [[]])],
	[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"
	    ;;
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
    # 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([
		#ifdef _WIN32
		    #error win32
		#endif
	    ], [],
	    ac_cv_win32=no,
	    ac_cv_win32=yes)
	)
	if test "$ac_cv_win32" != "yes"; then
	    AC_MSG_ERROR([${CC} cannot produce win32 executables.])
	fi




	hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -mwindows -municode -Dmain=xxmain"
	AC_CACHE_CHECK(for working -municode linker flag,
	    ac_cv_municode,
	AC_TRY_LINK([
	#include <windows.h>
	int APIENTRY wWinMain(HINSTANCE a, HINSTANCE b, LPWSTR c, int d) {return 0;}
	],
	[],
	    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

































    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"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \[$]@"







|



|
|
|




>
>
>




|


|
<
|
|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|







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
    # 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_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		#ifdef _WIN32
		    #error win32
		#endif
	    ]], [[]])],
	    [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_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])
	)
	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 -lwinspool"
	STLIB_LD='${AR} cr'
	RC_OUT=-o
	RC_TYPE=
	RC_INCLUDE=--include
	RC_DEFINE=--define
	RES=res.o
	MAKE_LIB="\${STLIB_LD} \[$]@"
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
	LDFLAGS_OPTIMIZE=

	case "${CC}" in
	    *++)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wno-format"
		;;
	    *)
		CFLAGS_WARNING="${CFLAGS_WARNING} -Wc++-compat -Wdeclaration-after-statement"
		;;
	esac

	# Specify the CC output file names based on the target name
	CC_OBJNAME="-o \[$]@"
	CC_EXENAME="-o \[$]@"








|







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 -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
	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])
		;;




	    ia64)
		MACHINE="IA64"
		AC_MSG_RESULT([   Using 64-bit $MACHINE mode])
		;;
	    *)
		AC_TRY_COMPILE([
		    #ifndef _WIN64
			#error 32-bit
		    #endif
		], [],
			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])
		fi
		;;
	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])







>
>
>
>


|


|



|
|
|


|
|
|







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
	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 IA64 $MACHINE mode])
		;;
	    *)
		AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
		    #ifndef _WIN64
			#error 32-bit
		    #endif
		]], [[]])],
			[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])
		fi
		;;
	esac
    else
	if test "${SHARED_BUILD}" = "0" ; then
	    # static
            AC_MSG_RESULT([using static flags])
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
	LIBFLAGSUFFIX=""

	if test "$do64bit" != "no" ; then
	    case "$do64bit" in
		amd64|x64|yes)
		    MACHINE="AMD64" ; # assume AMD64 as default 64-bit build
		    ;;



		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}"
	    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"

	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







>
>
>




















<
|
















|







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"

	    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 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
    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([
	    #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)
	)
	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([
#	    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)
	)
	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([],
	    [
		  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
    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)

])

#------------------------------------------------------------------------
# SC_WITH_TCL --
#
#	Location of the Tcl build directory.
#







|














|
|
|
|














|



|

|
|
|






<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<








|
<


|
|
|












>







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_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])
	)
	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_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])
	)
	if test "$tcl_cv_eh_disposition" = "no" ; then
	AC_DEFINE(EXCEPTION_DISPOSITION, int,
		[Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
	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_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
    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
#	extension can't assume that an executable Tcl shell exists at
#	build time.
#
# Arguments
#	none
#
# Results
#	Subst's the following values:
#		TCLSH_PROG
#------------------------------------------------------------------------

AC_DEFUN([SC_PROG_TCLSH], [
    AC_MSG_CHECKING([for tclsh])

    AC_CACHE_VAL(ac_cv_path_tclsh, [







|







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
#	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
#	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:
#		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}
    AC_MSG_RESULT($BUILD_TCLSH)
    AC_SUBST(BUILD_TCLSH)
])

#--------------------------------------------------------------------
# SC_TCL_CFG_ENCODING	TIP #59
#







|





|







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
#	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}\${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
#		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],
		[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" \







|







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,
	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" \

Changes to win/tcl.rc.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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 "ProductName", "Tcl " TCL_VERSION " for Windows\0"
            VALUE "ProductVersion", TCL_PATCH_LEVEL
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200







<

|







33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
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 "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

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
 * 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"





















#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 */








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








<
<
<
<
<
<
<
<
<
<
<
<







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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>












#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
 *----------------------------------------------------------------------
 */

#ifdef TCL_BROKEN_MAINARGS
int
main(
    int argc,			/* Number of command-line arguments. */
    char **argv1)
{
    TCHAR **argv;
    TCHAR *p;
#else
int
_tmain(
    int argc,			/* Number of command-line arguments. */
    TCHAR *argv[])		/* Values of command-line arguments. */
{
    TCHAR *p;
#endif


    /*
     * Set up the default locale to be standard "C" locale so parsing is
     * performed correctly.
     */

    setlocale(LC_ALL, "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
 *----------------------------------------------------------------------
 */

#ifdef TCL_BROKEN_MAINARGS
int
main(
    int argc,			/* Number of command-line arguments. */
    char **argv1)		/* Not used. */
{
    TCHAR **argv;

#else
int
_tmain(
    int argc,			/* Number of command-line arguments. */
    TCHAR *argv[])		/* Values of command-line arguments. */
{

#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
	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 */
    TclZipfs_AppHook(&argc, &argv);
#endif

    Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
    return 0;			/* Needed only to prevent compiler warning. */
}








|
|







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 (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
 *----------------------------------------------------------------------
 */

int
Tcl_AppInit(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    if ((Tcl_Init)(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }

#if defined(STATIC_BUILD) && defined(TCL_USE_STATIC_PACKAGES) && TCL_USE_STATIC_PACKAGES
    if (Registry_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(interp, "registry", Registry_Init, NULL);

    if (Dde_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticPackage(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);
#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
     * 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.
     */


    (Tcl_ObjSetVar2)(interp, Tcl_NewStringObj("tcl_rcFileName", -1), NULL,

	    Tcl_NewStringObj("~/tclshrc.tcl", -1), TCL_GLOBAL_ONLY);
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * setargv --







|



|



|




|






|















|










>
|
>
|







164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
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) {
	return TCL_ERROR;
    }

#if defined(STATIC_BUILD)
    if (Registry_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticLibrary(interp, "Registry", Registry_Init, NULL);

    if (Dde_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    Tcl_StaticLibrary(interp, "Dde", Dde_Init, Dde_SafeInit);
#endif

#ifdef TCL_TEST
    if (Tcltest_Init(interp) == TCL_ERROR) {
	return TCL_ERROR;
    }
    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_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,
	    "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
# 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@

# 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@'







|
<
<
<
<
<
<







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=''







# 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
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@'

# 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@'

# 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@'







|









|
|







75
76
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=''

# 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_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
# 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@'

# 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@'







|







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='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






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@'













>
>
>
>
>
>
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
/*
 * 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.
 *
 * 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);







|
|


















<
<
<
<
<
<
<
<







1
2
3
4
5
6
7
8
9
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 © 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. */









/*
 * 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
    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.
     */

    if (os.dwPlatformId != VER_PLATFORM_WIN32_NT) {
	Tcl_Panic("Windows NT is the only supported platform");
    }
}

/*
 *-------------------------------------------------------------------------
 *
 * TclWinNoBackslash --







|
|



|







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 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 7 is the minimum supported platform");
    }
}

/*
 *-------------------------------------------------------------------------
 *
 * TclWinNoBackslash --
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
		    alreadyStored = 1;
		    break;
		}
	    }
	    if (!alreadyStored) {
		dlPtr2 = (MountPointMap *)Tcl_Alloc(sizeof(MountPointMap));
		dlPtr2->volumeName = (WCHAR *)TclNativeDupInternalRep(Target);
		dlPtr2->driveLetter = (char) drive[0];
		dlPtr2->nextPtr = driveLetterLookup;
		driveLetterLookup = dlPtr2;
	    }
	}
    }

    /*







|







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 = (WCHAR) drive[0];
		dlPtr2->nextPtr = driveLetterLookup;
		driveLetterLookup = dlPtr2;
	    }
	}
    }

    /*
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
    /*
     * 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->nextPtr = driveLetterLookup;
    driveLetterLookup = dlPtr2;
    Tcl_MutexUnlock(&mountPointMap);
    return -1;
}

/*







|







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 = (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
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)

    __cpuid((int *)regsPtr, index);
    status = TCL_OK;

#elif defined(__GNUC__)
#   if defined(_WIN64)
    /*
     * Execute the CPUID instruction with the given index, and store results
     * off 'regPtr'.
     */

    __asm__ __volatile__(







|




|







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) && defined(HAVE_CPUID)

    __cpuid((int *)regsPtr, index);
    status = TCL_OK;

#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
	[ok]		"i"	(TCL_OK),
	[error]		"i"	(TCL_ERROR)
	:
	"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
    status = registration.status;

#   endif /* !_WIN64 */
#elif defined(_MSC_VER)
#   if defined(_WIN64)

    __cpuid(regsPtr, index);
    status = TCL_OK;

#   elif defined (_M_IX86)
    /*







|







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) && 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
	status = TCL_OK;
    } __except(EXCEPTION_EXECUTE_HANDLER) {
	/* do nothing */
    }

#   endif
#else


    /*
     * Don't know how to do assembly code for this compiler and/or
     * architecture.
     */
#endif
    return status;
}







>
>







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
/*
 * tclWinChan.c
 *
 *	Channel drivers for Windows channels based on files, command pipes and
 *	TCP sockets.
 *
 * Copyright (c) 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 "tclIO.h"






|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * tclWinChan.c
 *
 *	Channel drivers for Windows channels based on files, command pipes and
 *	TCP sockets.
 *
 * 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 "tclIO.h"
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129




































130
131
132
133
134
135
136
				 * 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,
			    Tcl_Interp *interp, int flags);
static int		FileEventProc(Tcl_Event *evPtr, int flags);
static int		FileGetHandleProc(ClientData instanceData,
			    int direction, ClientData *handlePtr);



static ThreadSpecificData *FileInit(void);
static int		FileInputProc(ClientData instanceData, char *buf,
			    int toRead, int *errorCode);
static int		FileOutputProc(ClientData 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,
			    int action);
static int		FileTruncateProc(ClientData instanceData,
			    Tcl_WideInt length);
static DWORD		FileGetType(HANDLE handle);
static int		NativeIsComPort(const WCHAR *nativeName);



/*
 * 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,
    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. */
};

/*
 * 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)





































/*
 *----------------------------------------------------------------------
 *
 * FileInit --
 *
 *	This function creates the window used to simulate file events.







|
|
|
|


|
|
>
>
>

|

|

|
|
|
|
|

|
|


>
>













|


















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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(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(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(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		FileOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);
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(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,
    NULL,			/* Set option proc. */
    FileGetOptionProc,		/* 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. */
};

/*
 * 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
 *	Destroys the communication window.
 *
 *----------------------------------------------------------------------
 */

static void
FileChannelExitHandler(
    TCL_UNUSED(ClientData))
{
    Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL);
}

/*
 *----------------------------------------------------------------------
 *







|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
 *	Destroys the communication window.
 *
 *----------------------------------------------------------------------
 */

static void
FileChannelExitHandler(
    TCL_UNUSED(void *))
{
    Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL);
}

/*
 *----------------------------------------------------------------------
 *
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
 *	Adjusts the block time if needed.
 *
 *----------------------------------------------------------------------
 */

void
FileSetupProc(
    TCL_UNUSED(ClientData),
    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)) {







|







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(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
 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
FileCheckProc(
    TCL_UNUSED(ClientData),
    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)) {







|







282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
FileCheckProc(
    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
 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
FileBlockProc(
    ClientData 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,







|







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(
    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
 *	Closes the physical channel
 *
 *----------------------------------------------------------------------
 */

static int
FileCloseProc(
    ClientData instanceData,	/* Pointer to FileInfo structure. */
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    FileInfo *fileInfoPtr = (FileInfo *)instanceData;
    FileInfo *infoPtr;
    ThreadSpecificData *tsdPtr;
    int errorCode = 0;







|







420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
 *	Closes the physical channel
 *
 *----------------------------------------------------------------------
 */

static int
FileCloseProc(
    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
     */

    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());
	    errorCode = errno;
	}
    }

    /*
     * See if this FileInfo* is still on the thread local list.
     */







|







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) {
	    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
 * Side effects:
 *	Moves the location at which the channel will be accessed in future
 *	operations.
 *
 *----------------------------------------------------------------------
 */

static Tcl_WideInt
FileWideSeekProc(
    ClientData instanceData,	/* File state. */
    Tcl_WideInt 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;








|

|
|







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 long long
FileWideSeekProc(
    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
    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);
	    *errorCodePtr = errno;
	    return -1;
	}
    }
    return (((Tcl_WideInt)((unsigned)newPos))
	    | ((Tcl_WideInt)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. */
{
    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);
	    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);
	    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());
	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.
     */







|




|
|




















|
|














|















|










|







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) {
	    Tcl_WinConvertError(winError);
	    *errorCodePtr = errno;
	    return -1;
	}
    }
    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(
    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) {
	    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) {
	    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)) {
	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
 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
FileInputProc(
    ClientData 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;








|







626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
FileInputProc(
    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
     * 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;
    }

    TclWinConvertError(GetLastError());
    *errorCode = errno;
    if (errno == EPIPE) {
	return 0;
    }
    return -1;
}








|


|







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 (int)bytesRead;
    }

    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
 *	Writes output on the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
FileOutputProc(
    ClientData 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());
	*errorCode = errno;
	return -1;
    }
    infoPtr->dirty = 1;
    return 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. */
    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 };








|




















|




|




















|







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(
    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) {
	Tcl_WinConvertError(GetLastError());
	*errorCode = errno;
	return -1;
    }
    infoPtr->dirty = 1;
    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(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileGetHandleProc(
    ClientData instanceData,	/* The file state. */
    int direction,		/* TCL_READABLE or TCL_WRITABLE */
    ClientData *handlePtr)	/* Where to store the handle.  */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;

    if (!TEST_FLAG(direction, infoPtr->validMask)) {
	return TCL_ERROR;
    }

    *handlePtr = (ClientData) infoPtr->handle;
    return TCL_OK;
}






























































































































































































/*
 *----------------------------------------------------------------------
 *
 * TclpOpenFileChannel --
 *
 *	Open an File based channel on Unix systems.







|

|







|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
FileGetHandleProc(
    void *instanceData,	/* The file state. */
    int direction,		/* TCL_READABLE or TCL_WRITABLE */
    void **handlePtr)	/* Where to store the handle.  */
{
    FileInfo *infoPtr = (FileInfo *)instanceData;

    if (!TEST_FLAG(direction, infoPtr->validMask)) {
	return TCL_ERROR;
    }

    *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 void
StoreElementInDict(
    Tcl_Obj *dictObj,
    const char *name,
    Tcl_Obj *valueObj)
{
    /*
     * We assume that the dict is being built fresh and that there's never any
     * duplicate keys.
     */

    Tcl_Obj *nameObj = Tcl_NewStringObj(name, TCL_INDEX_NONE);
    Tcl_DictObjPut(NULL, dictObj, nameObj, valueObj);
}

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) StoreElementInDict(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.
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
	    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)) {
    case O_RDONLY:
	accessMode = GENERIC_READ;
	channelPermissions = TCL_READABLE;
	break;
    case O_WRONLY:
	accessMode = GENERIC_WRITE;
	channelPermissions = TCL_WRITABLE;







|







1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't open \"%s\": filename is invalid on this platform",
		    TclGetString(pathPtr)));
	}
	return NULL;
    }

    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
     * 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());
	    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.
	 */

	channel = TclWinOpenSerialChannel(handle, channelName,
		channelPermissions);

	return channel;
    }







|









|







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
     * 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) {
	    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.
	 */

	channel = TclWinOpenSerialChannel(handle, channelName,
		channelPermissions);

	return channel;
    }
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
    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);
	if (interp) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't open \"%s\": %s",
		    TclGetString(pathPtr), Tcl_PosixError(interp)));
	}
	return NULL;
    }







|







1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
    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;
	}
	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
	 *
	 * 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());
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't reopen serial \"%s\": %s",
			TclGetString(pathPtr), Tcl_PosixError(interp)));
	    }
	    return NULL;
	}







|







1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
	 *
	 * Reopen channel for OVERLAPPED operation. Normally this shouldn't
	 * fail, because the channel exists.
	 */

	handle = TclWinSerialOpen(handle, nativeName, accessMode);
	if (handle == INVALID_HANDLE_VALUE) {
	    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
	    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,
		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);
	break;
    }

    return channel;
}

/*







|















|







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
	    writeFile = TclWinMakeFile(handle);
	}
	channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL);
	break;
    case FILE_TYPE_CHAR:
    case FILE_TYPE_DISK:
    case FILE_TYPE_UNKNOWN:
	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",
		(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
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_MakeFileChannel(
    ClientData rawHandle,	/* OS level handle */
    int mode)			/* ORed 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) {
	return NULL;
    }

    switch (FileGetType(handle)) {
    case FILE_TYPE_SERIAL:
	channel = TclWinOpenSerialChannel(handle, channelName, mode);
	break;







|
|












|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_MakeFileChannel(
    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 & (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
	    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);
	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







|







1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
	    writeFile = TclWinMakeFile(handle);
	}
	channel = TclpCreateCommandChannel(readFile, writeFile, NULL, 0, NULL);
	break;

    case FILE_TYPE_DISK:
    case FILE_TYPE_CHAR:
	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
	/*
	 * 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);
    }

    return channel;
}

/*
 *----------------------------------------------------------------------







|







1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
	/*
	 * Fall through, the handle is valid.
	 *
	 * Create the undefined channel, anyways, because we know the handle
	 * is valid to something.
	 */

	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
    }

    /*
     * 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 --
 *
 *	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(
    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==infoPtr->validMask) ? 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->watchMask = 0;
    infoPtr->flags = appendMode;
    infoPtr->handle = handle;
    infoPtr->dirty = 0;
    sprintf(channelName, "file%" TCL_Z_MODIFIER "x", (size_t) 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;
}

/*
 *----------------------------------------------------------------------
 *







<










|
















|



















>
|












|




<
|









<







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
    }

    /*
     * Set up the normal channel options for stdio handles.
     */

    if (Tcl_SetChannelOption(NULL,channel,"-translation","auto")!=TCL_OK ||

	    Tcl_SetChannelOption(NULL,channel,"-buffering",bufMode)!=TCL_OK) {
	Tcl_CloseEx(NULL, channel, 0);
	return (Tcl_Channel) NULL;
    }
    return channel;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
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)
		    ? 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 & (TCL_READABLE|TCL_WRITABLE|TCL_EXCEPTION);
    infoPtr->watchMask = 0;
    infoPtr->flags = appendMode;
    infoPtr->handle = handle;
    infoPtr->dirty = 0;

    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");


    return infoPtr->channel;
}

/*
 *----------------------------------------------------------------------
 *
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
FileThreadActionProc(
    ClientData instanceData,
    int action)
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    FileInfo *infoPtr = (FileInfo *)instanceData;

    if (action == TCL_CHANNEL_THREAD_INSERT) {
	infoPtr->nextPtr = tsdPtr->firstFilePtr;







|







1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
FileThreadActionProc(
    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
 */

static int
NativeIsComPort(
    const WCHAR *nativePath)	/* Path of file to access, native encoding. */
{
    const WCHAR *p = (const WCHAR *) nativePath;
    int i, len = wcslen(p);

    /*
     * 1. Look for com[1-9]:?
     */

    if ((len == 4) && (_wcsnicmp(p, L"com", 3) == 0)) {
	/*







|







1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
 */

static int
NativeIsComPort(
    const WCHAR *nativePath)	/* Path of file to access, native encoding. */
{
    const WCHAR *p = (const WCHAR *) nativePath;
    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
/*
 * tclWinConsole.c --
 *
 *	This file implements the Windows-specific console functions, and the
 *	"console" channel driver.
 *
 * Copyright (c) 1999 by Scriptics Corp.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */





#include "tclWinInt.h"



/*

 * The following variable is used to tell whether this module has been
 * initialized.
 */

static int initialized = 0;
















/*
 * 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.
 */





















TCL_DECLARE_MUTEX(consoleMutex)


/*
 * Bit masks used in the flags field of the ConsoleInfo structure below.



 */




#define CONSOLE_PENDING	 (1<<0)	/* Message is pending in the queue. */

#define CONSOLE_ASYNC	 (1<<1)	/* Channel is non-blocking. */
#define CONSOLE_READ_OPS (1<<4)	/* Channel supports read-related ops. */
#define CONSOLE_RESET    (1<<5)	/* Console mode needs to be reset. */








/*
 * Bit masks used in the sharedFlags field of the ConsoleInfo structure below.


 */











#define CONSOLE_EOF	  (1<<2)  /* Console has reached EOF. */
#define CONSOLE_BUFFERED  (1<<3)  /* Data was read into a buffer by the reader

				   * thread. */



#define CONSOLE_BUFFER_SIZE (8*1024)






/*
 * Structure containing handles associated with one of the special console
 * threads.
 */






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. */
    TclPipeThreadInfo *TI;	/* Thread info structure of writer and reader. */





} ConsoleThreadInfo;

/*
 * This structure describes per-instance data for a console based channel.
 */

























typedef struct ConsoleInfo {
    HANDLE handle;
    int type;


    struct ConsoleInfo *nextPtr;/* Pointer to next registered console. */
    Tcl_Channel channel;	/* Pointer to channel structure. */


    int validMask;		/* 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. */
    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];
				/* Data consumed by reader thread. */
} ConsoleInfo;

typedef struct {
    /*
     * The following pointer refers to the head of the list of consoles that
     * are being watched for file events.
     */

    ConsoleInfo *firstConsolePtr;
} ThreadSpecificData;

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
				 * events. */

    ConsoleInfo *infoPtr;	/* 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,
			    int mode);
static void		ConsoleCheckProc(ClientData clientData, int flags);
static int		ConsoleCloseProc(ClientData 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,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static void		ConsoleInit(void);
static int		ConsoleInputProc(ClientData instanceData, char *buf,
			    int toRead, int *errorCode);
static int		ConsoleOutputProc(ClientData instanceData,
			    const char *buf, int toWrite, int *errorCode);
static DWORD WINAPI	ConsoleReaderThread(LPVOID arg);
static int		ConsoleSetOptionProc(ClientData 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 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);









/*
 * 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. */
    NULL,			/* Flush proc. */






    NULL,			/* Handler proc. */


    NULL,			/* Wide seek proc. */
    ConsoleThreadActionProc,	/* Thread action proc. */




    NULL			/* Truncation proc. */











};





/*
 *----------------------------------------------------------------------
 *
 * ReadConsoleBytes, WriteConsoleBytes --

 *
 *	Wrapper for ReadConsoleW, that takes and returns number of bytes

 *	instead of number of WCHARS.
 *
 *----------------------------------------------------------------------
 */
































static BOOL





ReadConsoleBytes(
    HANDLE hConsole,
    LPVOID lpBuffer,

    DWORD nbytes,
    LPDWORD nbytesread)

{
    DWORD ntchars;








    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. 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.
     */
    do {
        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;
}
























static BOOL
WriteConsoleBytes(
    HANDLE hConsole,
    const void *lpBuffer,
    DWORD nbytes,
    LPDWORD nbyteswritten)
{



















    DWORD ntchars;

    BOOL result;









































    result = WriteConsoleW(hConsole, lpBuffer, nbytes / sizeof(WCHAR), &ntchars,
	    NULL);
    if (nbyteswritten != NULL) {
	*nbyteswritten = ntchars * sizeof(WCHAR);
    }

    return result;



}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleInit --
 *




|

|




>
>
>
>


>
>


>
|
<
<
|
<
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
|
|
<
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>


|
>
>
>

>
>
>

<
>
|
<
<
>
>
>
>
>
>
>


<
>
>

>
>
>
>
>
>
>
>
>

>
|
<
>
|
>
>
|
<
>
>
>
>
>
|
<
|
|
<
|
>
>
>
>
>
|
>
|
|
>
>
>
>
>
>
>
>
|
>
>
>
|
<
>
>
>
>
>
|



<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
<
>
>
|

>
>
|





|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
|
<
<
|
<







|
<
>
|









|
<
|
|


|
|
|
|



|

|

<
|


|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
|
>
|
>
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
>
>
>
>
>
>
>
>







|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
|
>
>
|
<
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
<
|

|
>

<
>
|

|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
|
|
|
>
|
|
>
|
<
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
<
|
|
|
>
|
<
|
<
<
|
|
>
>
|
|
|
<
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
>
|
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23


24

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46
47

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83


84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112

113
114
115
116
117
118

119
120

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
145
146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187
188
189
190
191
192






























193


194





195


196

197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
224
225
226
227
228
229
230
231

232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
/*
 * tclWinConsole.c --
 *
 *	This file implements the Windows-specific console functions, and the
 *	"console" channel driver. Windows 7 or later required.
 *
 * 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
 * most other drivers in the following respects:


 *

 * - 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.

 *
 * 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.

 *
 * 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;

/*
 * 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


/*
 * CONSOLE_BUFFER_SIZE is size of storage used in ring buffers.


 * 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

/*

 * 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_))

/*
 * The Win32 console API does not support non-blocking I/O in any form. Thus

 * 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.
 *

 * 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.
 *

 * Consoles are identified purely by handles and multiple threads may open
 * them (as stdin/stdout/stderr are shared).

 *
 * 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. */

    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.

 *
 * 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 */

    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 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 */






























#define CONSOLE_EVENT_QUEUED 0x0001 /* Notification event already queued */


#define CONSOLE_ASYNC        0x0002 /* Channel is non-blocking. */





#define CONSOLE_READ_OPS     0x0004 /* Channel supports read-related ops. */


} ConsoleChannelInfo;


/*
 * 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 events. */

    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(void *instanceData, int mode);

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(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(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		ConsoleOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);

static int		ConsoleSetOptionProc(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *value);
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		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. */
    NULL,                    /* Flush proc. */
    NULL,                    /* Handler proc. */
    NULL,                    /* Wide seek proc. */
    ConsoleThreadActionProc, /* Thread action proc. */
    NULL                     /* Truncation proc. */
};

/*
 *------------------------------------------------------------------------
 *
 * RingBufferInit --
 *
 *    Initializes the ring buffer to a given size.
 *
 * Results:
 *    None.
 *
 * Side effects:
 *    Panics on allocation failure.
 *
 *------------------------------------------------------------------------
 */
static void
RingBufferInit(
    RingBuffer *ringPtr,
    Tcl_Size capacity)
{
    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 (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;
    }
    if (leadLen >= dstCapacity) {
	if (dstPtr) {
	    memmove(dstPtr, ringPtr->start + ringPtr->bufPtr, dstCapacity);
	}
	ringPtr->start += dstCapacity;
    } else {
	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

/*
 *------------------------------------------------------------------------
 *
 * 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,
    WCHAR *lpBuffer,
    Tcl_Size nChars,
    Tcl_Size *nCharsReadPtr)
{




    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, 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
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;
	    Tcl_CreateExitHandler(ProcExitHandler, NULL);
	}
	Tcl_MutexUnlock(&consoleMutex);
    }

    if (TclThreadDataKeyGet(&dataKey) == NULL) {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	tsdPtr->firstConsolePtr = NULL;
	Tcl_CreateEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL);
	Tcl_CreateThreadExitHandler(ConsoleExitHandler, NULL);
    }
}

/*
 *----------------------------------------------------------------------







|
|
|
|


|





|







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
ConsoleInit(void)
{
    /*
     * Check the initialized flag first, then check again in the mutex. This
     * is a speed enhancement.
     */

    if (!gInitialized) {
	AcquireSRWLockExclusive(&gConsoleLock);
	if (!gInitialized) {
	    gInitialized = 1;
	    Tcl_CreateExitHandler(ProcExitHandler, NULL);
	}
	ReleaseSRWLockExclusive(&gConsoleLock);
    }

    if (TclThreadDataKeyGet(&dataKey) == NULL) {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	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
 *	Removes the console event source.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleExitHandler(
    TCL_UNUSED(ClientData))
{
    Tcl_DeleteEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL);
}

/*
 *----------------------------------------------------------------------
 *







|







674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
 *	Removes the console event source.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleExitHandler(
    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
 *	Resets the process list.
 *
 *----------------------------------------------------------------------
 */

static void
ProcExitHandler(
    TCL_UNUSED(ClientData))
{
    Tcl_MutexLock(&consoleMutex);
    initialized = 0;


    Tcl_MutexUnlock(&consoleMutex);





































}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleSetupProc --
 *
 *	This procedure is invoked before Tcl_DoOneEvent blocks waiting for an
 *	event.


 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Adjusts the block time if needed.
 *
 *----------------------------------------------------------------------
 */

void
ConsoleSetupProc(
    TCL_UNUSED(ClientData),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    ConsoleInfo *infoPtr;
    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.

     */






    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 (WaitForRead(infoPtr, 0) >= 0) {
		block = 0;
	    }
	}

    }
    if (!block) {

	Tcl_SetMaxBlockTime(&blockTime);
    }
}

/*
 *----------------------------------------------------------------------
 *







|

|
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>








|
>
>












|


|


<






|
>

>

>
>
>
>
|
|
>
>
>
>
>
>
|
|
|
|
|
|
|
<
<
|
|
>
|

>







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
 *	Resets the process list.
 *
 *----------------------------------------------------------------------
 */

static void
ProcExitHandler(
    TCL_UNUSED(void *))
{
    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. 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(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    ConsoleChannelInfo *chanInfoPtr;
    Tcl_Time blockTime = { 0, 0 };
    int block = 1;


    if (!(flags & TCL_FILE_EVENTS)) {
	return;
    }

    /*
     * 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);
	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);


	}
    }
    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
 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleCheckProc(
    TCL_UNUSED(ClientData),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    ConsoleInfo *infoPtr;

    int needEvent;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!(flags & TCL_FILE_EVENTS)) {
	return;
    }



    /*
     * Queue events for any ready consoles that don't already have events




     * queued.
     */





    for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL;
	    infoPtr = infoPtr->nextPtr) {



	if (infoPtr->flags & CONSOLE_PENDING) {

	    continue;
	}



	/*

	 * Queue an event if the console is signaled for reading or writing.
	 */



	needEvent = 0;


	if (infoPtr->watchMask & TCL_WRITABLE) {

	    if (WaitForSingleObject(infoPtr->writer.readyEvent,
		    0) != WAIT_TIMEOUT) {
		needEvent = 1;
	    }
	}







	if (infoPtr->watchMask & TCL_READABLE) {
	    if (WaitForRead(infoPtr, 0) >= 0) {

		needEvent = 1;
	    }
	}


	if (needEvent) {
	    ConsoleEvent *evPtr = (ConsoleEvent *)Tcl_Alloc(sizeof(ConsoleEvent));


	    infoPtr->flags |= CONSOLE_PENDING;


	    evPtr->header.proc = ConsoleEventProc;
	    evPtr->infoPtr = infoPtr;
	    Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);
	}
    }
}



/*
 *----------------------------------------------------------------------
 *
 * 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. */
    int mode)			/* TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)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;
    } else {
	infoPtr->flags &= ~CONSOLE_ASYNC;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *







|


|
>

<





>
>

<
>
>
>
>
|

>

>
>
>
|
|
>
>
>
|
>



>
>
|
>
|
<
>
|
>

>
>
|
>
|
<
|

<
|
>
>
>
>
>
>
|
<
>
|


>




>
|
>
>

|



|
>
|
>


















|



|










|

|







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
 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleCheckProc(
    TCL_UNUSED(void *),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    ConsoleChannelInfo *chanInfoPtr;
    Tcl_ThreadId me;
    int needEvent;


    if (!(flags & TCL_FILE_EVENTS)) {
	return;
    }

    me = Tcl_GetCurrentThread();

    /*

     * 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;

	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 */

	if (handleInfoPtr == NULL) {
	    /* Stale event */

	    continue;
	}

	needEvent = 0;
	AcquireSRWLockShared(&handleInfoPtr->lock);
	/* Rememeber channel is read or write, never both */
	if (chanInfoPtr->watchMask & TCL_READABLE) {
	    if (RingBufferLength(&handleInfoPtr->buffer) > 0
		    || handleInfoPtr->lastError != ERROR_SUCCESS) {

		needEvent = 1; /* Input data available or error/EOF */
	    }

	    /*
	     * 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 (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 */
	    chanInfoPtr->flags |= CONSOLE_EVENT_QUEUED;
	    chanInfoPtr->numRefs += 1; /* So it does not go away while event
					  is in queue */
	    evPtr->header.proc = ConsoleEventProc;
	    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(
    void *instanceData,		/* Instance data for channel. */
    int mode)			/* TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
    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) {
	chanInfoPtr->flags |= CONSOLE_ASYNC;
    } else {
	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
 *	Closes the physical channel.
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleCloseProc(
    ClientData instanceData,	/* Pointer to ConsoleInfo structure. */
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    ConsoleInfo *consolePtr = (ConsoleInfo *)instanceData;

    int errorCode = 0;
    ConsoleInfo *infoPtr, **nextPtrPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);


    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.

     */

    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;
	}
    }

    consolePtr->watchMask &= consolePtr->validMask;

    /*
     * Remove the file from the list of watched files.
     */

    for (nextPtrPtr = &tsdPtr->firstConsolePtr, infoPtr = *nextPtrPtr;
	    infoPtr != NULL;
	    nextPtrPtr = &infoPtr->nextPtr, infoPtr = *nextPtrPtr) {
	if (infoPtr == (ConsoleInfo *) consolePtr) {
	    *nextPtrPtr = infoPtr->nextPtr;
	    break;
	}
    }
    if (consolePtr->writeBuf != NULL) {







	Tcl_Free(consolePtr->writeBuf);



	consolePtr->writeBuf = 0;









    }

































    Tcl_Free(consolePtr);


    return errorCode;
}

/*
 *----------------------------------------------------------------------
 *







|



|
>

|
<
>




<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
>

<

|
|
|
|
|
|
|
|
|
<

<
<
<
|
|
<
|
|
|



|
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>







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
 *	Closes the physical channel.
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleCloseProc(
    void *instanceData,	/* Pointer to ConsoleChannelInfo structure. */
    TCL_UNUSED(Tcl_Interp *),
    int flags)
{
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    ConsoleHandleInfo *handleInfoPtr;
    int errorCode = 0;
    ConsoleChannelInfo **nextPtrPtr;

    int closeHandle;

    if ((flags & (TCL_CLOSE_READ | TCL_CLOSE_WRITE)) != 0) {
	return EINVAL;
    }

    /*
















































     * 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) != chanInfoPtr->handle)
		&& (GetStdHandle(STD_OUTPUT_HANDLE) != chanInfoPtr->handle)
		&& (GetStdHandle(STD_ERROR_HANDLE) != chanInfoPtr->handle))) {
	closeHandle = 1;
    } else {
	closeHandle = 0;
    }

    AcquireSRWLockExclusive(&gConsoleLock);





    /* Remove channel from watchers' list */
    for (nextPtrPtr = &gWatchingChannelList; *nextPtrPtr != NULL;

	    nextPtrPtr = &(*nextPtrPtr)->nextWatchingChannelPtr) {
	if (*nextPtrPtr == (ConsoleChannelInfo *) chanInfoPtr) {
	    *nextPtrPtr = (*nextPtrPtr)->nextWatchingChannelPtr;
	    break;
	}
    }

    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
 *	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. */
    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;




    *errorCode = 0;






    /*
     * Synchronize with the reader thread.
     */

    result = WaitForRead(infoPtr, (infoPtr->flags & CONSOLE_ASYNC) ? 0 : 1);




    /*
     * If an error occurred, return immediately.


     */

    if (result == -1) {
	*errorCode = errno;
	return -1;
    }

    if (infoPtr->readFlags & CONSOLE_BUFFERED) {
	/*
	 * Data is stored in the buffer.




	 */

	if (bufSize < (infoPtr->bytesRead - infoPtr->offset)) {
	    memcpy(buf, &infoPtr->buffer[infoPtr->offset], bufSize);
	    bytesRead = bufSize;
	    infoPtr->offset += bufSize;
	} else {












	    memcpy(buf, &infoPtr->buffer[infoPtr->offset], bufSize);






	    bytesRead = infoPtr->bytesRead - infoPtr->offset;











	    /*


	     * Reset the buffer.
	     */


	    infoPtr->readFlags &= ~CONSOLE_BUFFERED;


	    infoPtr->offset = 0;
	}






	return bytesRead;
    }




    /*
     * 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.



     */



    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.

	 */









	buf[count] = '\0';


	return count;





    }


    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * 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. */
    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;

    *errorCode = 0;

    /* avoid blocking if pipe-thread exited */
    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
	 * the channel is in non-blocking mode.
	 */


	errno = EWOULDBLOCK;




	goto error;


    }



    /*



     * Check for a background error on the last write.
     */






    if (infoPtr->writeError) {
	TclWinConvertError(infoPtr->writeError);
	infoPtr->writeError = 0;

	goto error;
    }

    if (infoPtr->flags & CONSOLE_ASYNC) {
	/*


	 * The console is non-blocking, so copy the data into the output
	 * buffer and restart the writer thread.
	 */

	if (toWrite > infoPtr->writeBufLen) {
	    /*



	     * Reallocate the buffer to be large enough to hold the data.
	     */




	    if (infoPtr->writeBuf) {

		Tcl_Free(infoPtr->writeBuf);


	    }





	    infoPtr->writeBufLen = toWrite;

	    infoPtr->writeBuf = (char *)Tcl_Alloc(toWrite);





	}
	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
	 * avoids an unnecessary copy.


	 */

	if (WriteConsoleBytes(infoPtr->handle, buf, (DWORD) toWrite,

		&bytesWritten) == FALSE) {

	    TclWinConvertError(GetLastError());
	    goto error;

	}
    }
    return bytesWritten;


  error:
    *errorCode = errno;


    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleEventProc --
 *







<


|
|




|
>
|
|
>
>
>



>
>
>
>
>
|
<
<
|
|
>

>
>
|
<
>
>
|
|
<
<
|
|
<
<

|
>
>
>
>

|
<
|
|
<
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
<
>
>
|
|
|
>
|
>
>
|
<
|
>
>
>
>
>
|
<
|
>
>
>
|
<
<
<
>
>
>
|
>
>
|
<
<
>

<
<
<
|
>
|
>

>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>


>
|



















<


|




|
|
|



|
<
<
<
<
|
<
|
>
|
|
>
>
>
>
|
>
>

>
>

<
>
>
>
|
<
>
>
>
>
>
|
|
|
|
>
|
|

<

>
>
|
|
<
|
|
<
>
>
>
|
|
>
|
>
>
|
>
|
>
>

>
>
>
>
>
|
>
|
>
>
>
>
>
|
<
<
<
<
<
|
|
>
>
|
<
>
>
|
|
|
>
|
>
|
|
>
|
|
|
>
|
<
<
>
>
|







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
 *	indication is returned in an output argument.
 *
 * Side effects:
 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleInputProc(
    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. */
{
    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 */


    }
    AcquireSRWLockExclusive(&handleInfoPtr->lock);
    ReleaseSRWLockShared(&gConsoleLock); /* AFTER acquiring handleInfoPtr->lock */

    while (1) {
	numRead = RingBufferOut(&handleInfoPtr->buffer, bufPtr, bufSize, 1);
	/*

	 * Note: even if channel is closed or has an error, as long there is
	 * buffered data, we will pass it up.
	 */
	if (numRead != 0) {


	    break;
	}


	/*
	 * 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 (handleInfoPtr->lastError == ERROR_INVALID_HANDLE) {
		numRead = 0; /* Treat as EOF */

	    } 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.)
	 *

	 * 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);

	    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 {
		/*



		 * 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;
	    }


	}
	/*



	 * 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;
	}

	/* 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 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(
    void *instanceData,		/* Console state. */
    const char *buf,		/* The data buffer. */
    int toWrite,		/* How many bytes to write? */
    int *errorCode)		/* Where to store error code. */
{
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    ConsoleHandleInfo *handleInfoPtr;
    Tcl_Size numWritten;

    *errorCode = 0;

    if (chanInfoPtr->handle == INVALID_HANDLE_VALUE) {




	/* Some other thread would have *previously* closed the stdio handle */

	*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 */


    /* Keep looping until all written. Break out for async and errors */
    numWritten = 0;
    while (1) {
	/* Check for error and closing on every loop. */

	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;
	}


	/*
	 * We can either write directly or through the console thread's
	 * ring buffer. We have to do the latter when
	 * (1) the operation is async since WriteConsoleChars is always blocking
	 * (2) when there is already data in the ring buffer because we don't

	 *     want to reorder output from within a thread
	 * (3) when there are an odd number of bytes since WriteConsole

	 *     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.
	     */
	    WakeConditionVariable(&handleInfoPtr->consoleThreadCV);
	    if (!SleepConditionVariableSRW(&handleInfoPtr->interpThreadCV,
		    &handleInfoPtr->lock, INFINITE, 0)) {
		/* Report the error */
		Tcl_WinConvertError(GetLastError());
		*errorCode = Tcl_GetErrno();
		numWritten = -1;
		break;
	    }





	} else {
	    /* Direct output */
	    DWORD winStatus;
	    HANDLE consoleHandle = handleInfoPtr->console;
	    /* Unlock before blocking in WriteConsole */

	    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 */
    }


    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
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;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    if (!(flags & TCL_FILE_EVENTS)) {
	return 0;
    }


    /*
     * 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.
     */

    for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL;
	    infoPtr = infoPtr->nextPtr) {
	if (consoleEvPtr->infoPtr == infoPtr) {
	    infoPtr->flags &= ~CONSOLE_PENDING;
	    break;
	}
    }

    /*
     * Remove stale events.




     */

    if (!infoPtr) {
	return 1;
    }

    /*
     * Check to see if the console is readable. Note that we can't tell if a
     * console is writable, so we always report it as being writable unless we
     * have detected EOF.

     */

    mask = 0;



    if (infoPtr->watchMask & TCL_WRITABLE) {
	if (WaitForSingleObject(infoPtr->writer.readyEvent,
		0) != WAIT_TIMEOUT) {
	    mask = TCL_WRITABLE;
	}
    }


    if (infoPtr->watchMask & TCL_READABLE) {
	if (WaitForRead(infoPtr, 0) >= 0) {
	    if (infoPtr->readFlags & CONSOLE_EOF) {
		mask = TCL_READABLE;
	    } else {


		mask |= TCL_READABLE;
	    }

	}
    }

    /*
     * Inform the channel of the events.


     */





    Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask & mask);















    return 1;
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleWatchProc --







|
>
|
<





>

<
|
|
|


<
<
<
<
<
<
<
<

<
>
>
>
>

|
|
<
|
<

|
<
<
>

|
|
>
>
>
|
<
<
|
|
|
|
>
|
<
|

|
>
>
|

>




|
>
>

>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
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;
    ConsoleChannelInfo *chanInfoPtr;
    int freeChannel;
    int mask = 0;


    if (!(flags & TCL_FILE_EVENTS)) {
	return 0;
    }

    chanInfoPtr = consoleEvPtr->chanInfoPtr;
    /*

     * 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.
     */









    /*

     * 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.
     */
    AcquireSRWLockShared(&gConsoleLock);
    chanInfoPtr->flags &= ~CONSOLE_EVENT_QUEUED;



    /*
     * Only handle the event if the Tcl channel has not gone away AND is


     * still owned by this thread AND is still watching events.
     */
    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) {


		mask = TCL_READABLE;
	    }
	} else {
	    AcquireSRWLockShared(&handleInfoPtr->lock);
	    /* Remember at most one of READABLE, WRITABLE set */
	    if ((chanInfoPtr->watchMask & TCL_READABLE)

		    && RingBufferLength(&handleInfoPtr->buffer)) {
		mask = TCL_READABLE;
	    } else if ((chanInfoPtr->watchMask & TCL_WRITABLE)
		    && RingBufferHasFreeSpace(&handleInfoPtr->buffer)) {
		/* Generate write event space available */
		mask = TCL_WRITABLE;
	    }
	    ReleaseSRWLockShared(&handleInfoPtr->lock);
	}
    }

    /*
     * 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 */
    }

    /* 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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleWatchProc(
    ClientData instanceData,	/* Console state. */
    int mask)			/* What events to watch for, OR-ed combination
				 * of TCL_READABLE, TCL_WRITABLE and
				 * TCL_EXCEPTION. */
{
    ConsoleInfo **nextPtrPtr, *ptr;
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;
    int oldMask = infoPtr->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) {
	Tcl_Time blockTime = { 0, 0 };

	if (!oldMask) {


	    infoPtr->nextPtr = tsdPtr->firstConsolePtr;

	    tsdPtr->firstConsolePtr = infoPtr;











	}


	Tcl_SetMaxBlockTime(&blockTime);
    } else if (oldMask) {
	/*
	 * Remove the console from the list of watched consoles.
	 */


	for (nextPtrPtr = &(tsdPtr->firstConsolePtr), ptr = *nextPtrPtr;
		ptr != NULL;
		nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) {
	    if (infoPtr == ptr) {
		*nextPtrPtr = ptr->nextPtr;
		break;
	    }
	}

    }
}

/*
 *----------------------------------------------------------------------
 *
 * ConsoleGetHandleProc --







|
|
|
<

|
|
|
<






|
|



>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>


<
|
<

>
|

|
|
|



>







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
ConsoleWatchProc(
    void *instanceData,		/* Console state. */
    int newMask)		/* What events to watch for, one of
				 * of TCL_READABLE, TCL_WRITABLE */

{
    ConsoleChannelInfo **nextPtrPtr, *ptr;
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    int oldMask = chanInfoPtr->watchMask;


    /*
     * 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.
     */

    chanInfoPtr->watchMask = newMask & chanInfoPtr->permissions;
    if (chanInfoPtr->watchMask) {
	Tcl_Time blockTime = { 0, 0 };

	if (!oldMask) {
	    AcquireSRWLockExclusive(&gConsoleLock);
	    /* Add to list of watched channels */
	    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 from list of watched channels */


	AcquireSRWLockExclusive(&gConsoleLock);
	for (nextPtrPtr = &gWatchingChannelList, ptr = *nextPtrPtr;
		ptr != NULL;
		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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleGetHandleProc(
    ClientData instanceData,	/* The console state. */
    TCL_UNUSED(int) /*direction*/,
    ClientData *handlePtr)	/* Where to store the handle. */
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)instanceData;




    *handlePtr = infoPtr->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. */
    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) {
	/*
	 * 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.

	     */

	    errno = EWOULDBLOCK;

	    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.
	     */

	    if (infoPtr->readFlags & CONSOLE_BUFFERED) {
		return 0;
	    } else {
		return -1;
	    }
	}

	/*
	 * If there is data in the buffer, the console must be readable (since
	 * it is a line-oriented device).
	 */

	if (infoPtr->readFlags & CONSOLE_BUFFERED) {
	    return 1;
	}

	/*
	 * There wasn't any data available, so reset the thread and try again.
	 */

	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.
 *
 * Side effects:
 *	Signals the main thread when input become available. May cause the
 *	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)
{







    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.





















	 */





































	if (!TclPipeThreadWaitForSignal(&pipeTI)) {


	    /* exit */














	    break;
	}
	if (!infoPtr) {
	    infoPtr = (ConsoleInfo *)pipeTI->clientData;
	    handle = (HANDLE *)infoPtr->handle;
	    threadInfo = &infoPtr->reader;
	}


	/*
	 * Look for data on the console, but first ignore any events that are
	 * not KEY_EVENTs.
	 */

	if (ReadConsoleBytes(handle, infoPtr->buffer, CONSOLE_BUFFER_SIZE,
		(LPDWORD) &infoPtr->bytesRead) != FALSE) {
	    /*
	     * Data was stored in the buffer.
	     */

	    infoPtr->readFlags |= CONSOLE_BUFFERED;
	} else {
	    DWORD err = GetLastError();

	    if (err == (DWORD) EOF) {
		infoPtr->readFlags = CONSOLE_EOF;
	    }
	    done = 1;
	}

	/*
	 * Signal the main thread by signalling the readable event and then
	 * waking up the notifier thread.
	 */

	SetEvent(threadInfo->readyEvent);

	/*
	 * Alert the foreground thread. Note that we need to treat this like a
	 * critical section so the foreground thread does not terminate this
	 * thread while we are holding a mutex in the notifier code.
	 */

	Tcl_MutexLock(&consoleMutex);
	if (infoPtr->threadId != NULL) {
	    /*
	     * TIP #218. When in flight ignore the event, no one will receive
	     * it anyway.
	     */

	    Tcl_ThreadAlert(infoPtr->threadId);
	}
	Tcl_MutexUnlock(&consoleMutex);
    }

    /* 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
 *	cause the main thread to wake up by posting a message.
 *
 *----------------------------------------------------------------------
 */

static DWORD WINAPI
ConsoleWriterThread(
    LPVOID 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) {






	/*
	 * Wait for the main thread to signal before attempting to write.


	 */
	if (!TclPipeThreadWaitForSignal(&pipeTI)) {
	    /* exit */
	    break;
	}

	if (!infoPtr) {
	    infoPtr = (ConsoleInfo *)pipeTI->clientData;
	    handle = (HANDLE *)infoPtr->handle;
	    threadInfo = &infoPtr->writer;




	}


	buf = infoPtr->writeBuf;
	toWrite = infoPtr->toWrite;



	/*
	 * Loop until all of the bytes are written or an error occurs.
	 */






	while (toWrite > 0) {


	    if (WriteConsoleBytes(handle, buf, (DWORD) toWrite,

		    &count) == FALSE) {

		infoPtr->writeError = GetLastError();





		done = 1;




		break;
	    }
	    toWrite -= count;
	    buf += count;
	}



	/*
	 * 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
	 * critical section so the foreground thread does not terminate this
	 * thread while we are holding a mutex in the notifier code.
	 */


	Tcl_MutexLock(&consoleMutex);

	if (infoPtr->threadId != NULL) {
	    /*
	     * TIP #218. When in flight ignore the event, no one will receive






	     * it anyway.
	     */








	    Tcl_ThreadAlert(infoPtr->threadId);
	}
	Tcl_MutexUnlock(&consoleMutex);
    }


    /* Worker exit, so inform the main thread or free TI-structure (if owned) */
    TclPipeThreadExit(&pipeTI);

    return 0;
}









































































































/*
 *----------------------------------------------------------------------
 *
 * 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;
    DWORD modes;

    ConsoleInit();



    /*
     * See if a channel with this handle already exists.
     */


    infoPtr = (ConsoleInfo *)Tcl_Alloc(sizeof(ConsoleInfo));
    memset(infoPtr, 0, sizeof(ConsoleInfo));

    infoPtr->validMask = permissions;
    infoPtr->handle = handle;
    infoPtr->channel = (Tcl_Channel) NULL;

    wsprintfA(encoding, "cp%d", GetConsoleCP());

    infoPtr->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);

    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;
	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);







    }

    if (permissions & TCL_WRITABLE) {












	infoPtr->writer.readyEvent = CreateEventW(NULL, TRUE, TRUE, NULL);
	infoPtr->writer.thread = CreateThread(NULL, 256, ConsoleWriterThread,
		TclPipeThreadCreateTI(&infoPtr->writer.TI, infoPtr,
			infoPtr->writer.readyEvent), 0, NULL);
	SetThreadPriority(infoPtr->writer.thread, THREAD_PRIORITY_HIGHEST);

    }




    /*
     * 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 {}");
    Tcl_SetChannelOption(NULL, infoPtr->channel, "-encoding", "utf-16");
    return infoPtr->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,
    int action)
{
    ConsoleInfo *infoPtr = (ConsoleInfo *)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.
     */

    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();
	if (infoPtr->channel != NULL) {
	    infoPtr->threadId = Tcl_GetChannelThread(infoPtr->channel);
	}
    } else {
	infoPtr->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. */
    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;
    int len = strlen(optionName);
    int vlen = strlen(value);

    /*
     * Option -inputmode normal|password|raw
     */

    if ((infoPtr->flags & CONSOLE_READ_OPS) && (len > 1) &&
	    (strncmp(optionName, "-inputmode", len) == 0)) {
	DWORD mode;

	if (GetConsoleMode(infoPtr->handle, &mode) == 0) {
	    TclWinConvertError(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;
	    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) {
	    /*
	     * Reset to the initial mode, whatever that is.
	     */

	    mode = infoPtr->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);
	    }
	    return TCL_ERROR;
	}
	if (SetConsoleMode(infoPtr->handle, mode) == 0) {
	    TclWinConvertError(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) {
	return Tcl_BadChannelOption(interp, optionName, "inputmode");
    } else {
	return Tcl_BadChannelOption(interp, optionName, "");
    }
}

/*







|

|

|

>
>
>
|
|
|
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
>
>
>
>
>
|
>
|
>
>
>
>
>
|
|
|
<
<

<
<
<
|
|
|
<
<
<

<
<
<
<
|
<
<
>
|
|
<
>
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
>
>
>
>
>
|
|
|
<
|
<
<
|
<
|
<
|
<
<
|
<


|
<
<
<
|
<
<
|
|
<









|


|
<
<








>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>


<
<
<
<
|
|

<
<
<
<
|
|
<
<
<
<

|
<
<
|
<
<
<
<
<
|

<
<
<
|
<
|
<
|
<
<
<
|
<
|
<
<
<
|
|
<
|
<
<
|
<
<
















<
|
<



<




>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
|
>
|
>
>
>
>
|
|
>
>
>
>
|
>
>
|
>
>
>
>
>
>
|
<
>
>
|
<
<
|
|
>
|
<
|
|
>
>
>
>
|
>
|
|
|
>
>
|
<
|
<
>

>
>
>
>
|
>
>
|
>
|
>
|
>
>
>
>
>
|
>
>
>
>


|
|


>
>

<
<
<
<
<
|
|
|
<
<

>

|
>
|
|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
|
<
|
|
|
>

<
|




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

















<






|
|
<

|
>
>
|
|
<
<
>

|
|

|
|
|

<
<
|







<
|
<
<








|
<
|
|
|
>
|
>
>
>
>
|
|
>
>
>
>
>
>
|
>
|
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>


<
>
>
>
>
>
>

>
>
>
>
>
|
<
|
|
|
>
|
>
>
>


|



|
<
|
|




















|


|

<
<
<
<
<
<
|
<

<
<
<
<
<
<
<
<
|
<
|
<

|

<



















<


|




|







|



|
|







|
>
|
|
|

|
|
|



<
|






|



|
|








<
<
<
<
<
<
<
<
<



|







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(
    void *instanceData,		/* The console state. */
    TCL_UNUSED(int) /*direction*/,
    void **handlePtr)		/* Where to store the handle. */
{
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;

    if (chanInfoPtr->handle == INVALID_HANDLE_VALUE) {
	return TCL_ERROR;
    } else {
	*handlePtr = chanInfoPtr->handle;
	return TCL_OK;
    }
}


















/*
 *------------------------------------------------------------------------
 *
 * 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)


{



    INPUT_RECORD input[10];
    DWORD count;
    DWORD i;








    /*


     * Need at least one keyboard event.
     */
    if (PeekConsoleInputW(consoleHandle, input,

	    sizeof(input) / sizeof(input[0]), &count) == FALSE) {
	return -1;
    }


























    /*
     * 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]))) {

	return 1;


    }

    for (i = 0; i < count; ++i) {

	if (input[i].EventType == KEY_EVENT


		&& input[i].Event.KeyEvent.bKeyDown) {

	    return 1;
	}
    }



    return 0;


}


/*
 *----------------------------------------------------------------------
 *
 * ConsoleReaderThread --
 *
 *	This function runs in a separate thread and waits for input to become
 *	available on a console.
 *
 * Results:
 *	Always 0.
 *
 * Side effects:
 *	Signals the main thread when input become available.


 *
 *----------------------------------------------------------------------
 */

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];

    /*
     * 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
	     * 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;
		}
	    }
	} 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;
	}




    }
    ReleaseSRWLockExclusive(&gConsoleLock);





    /* No need for relocking - no other thread should have access to it now */
    RingBufferClear(&handleInfoPtr->buffer);





    if (handleInfoPtr->console != INVALID_HANDLE_VALUE


	    && handleInfoPtr->lastError != ERROR_INVALID_HANDLE) {





	SetConsoleMode(handleInfoPtr->console, handleInfoPtr->initMode);
	/*



	 * 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.



	 */
    }




    Tcl_Free(handleInfoPtr);



    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.

 *
 *----------------------------------------------------------------------
 */

static DWORD WINAPI
ConsoleWriterThread(
    LPVOID arg)
{
    ConsoleHandleInfo *handleInfoPtr = (ConsoleHandleInfo *) arg;
    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) {
		/*

		 * Sole reference. That's this thread. Exit since no clients
		 * and no buffered output.
		 */


		break;
	    }
	    /* Wake up any threads waiting synchronously. */
	    WakeConditionVariable(&handleInfoPtr->interpThreadCV);

	    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);
	}

	/* 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 (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;
	    }
	    numBytes -= numWChars * sizeof(WCHAR);
	    offset += numWChars * sizeof(WCHAR);
	}

	/* Wake up any threads waiting synchronously. */
	WakeConditionVariable(&handleInfoPtr->interpThreadCV);
	/*





	 * Wake up all channels registered for file events. Note in
	 * order to follow the locking hierarchy, we cannot hold any locks
	 * when calling NudgeWatchers.


	 */
	NudgeWatchers(consoleHandle);

	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;
	}

    }
    ReleaseSRWLockExclusive(&gConsoleLock);

    RingBufferClear(&handleInfoPtr->buffer);


    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)
{
    ConsoleChannelInfo *chanInfoPtr;
    ConsoleHandleInfo *handleInfoPtr;


    /* A console handle can either be input or output, not both */
    if (permissions != TCL_READABLE && permissions != TCL_WRITABLE) {
	return NULL;
    }



    ConsoleInit();

    chanInfoPtr = (ConsoleChannelInfo *)Tcl_Alloc(sizeof(*chanInfoPtr));
    memset(chanInfoPtr, 0, sizeof(*chanInfoPtr));

    chanInfoPtr->permissions = permissions;
    chanInfoPtr->handle = handle;
    chanInfoPtr->channel = (Tcl_Channel) NULL;



    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).
     */


    TclWinGenerateChannelName(channelName, "file", chanInfoPtr);



    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.
	 */

	chanInfoPtr->flags |= CONSOLE_READ_OPS;

	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;
    }


    /*
     * 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
     */
    AcquireSRWLockExclusive(&handleInfoPtr->lock);

    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);

    /*
     * 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, chanInfoPtr->channel, "-translation", "auto");

    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(
    void *instanceData,
    int action)
{
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;







    /* No need for any locks as no other thread will be writing to it */

    if (action == TCL_CHANNEL_THREAD_INSERT) {








	ConsoleInit(); /* Needed to set up event source handlers for this thread */

	chanInfoPtr->threadId = Tcl_GetCurrentThread();

    } else {
	chanInfoPtr->threadId = NULL;
    }

}

/*
 *----------------------------------------------------------------------
 *
 * 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(
    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. */
{
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;
    int len = strlen(optionName);
    int vlen = strlen(value);

    /*
     * Option -inputmode normal|password|raw
     */

    if ((chanInfoPtr->flags & CONSOLE_READ_OPS) && (len > 1) &&
	    (strncmp(optionName, "-inputmode", len) == 0)) {
	DWORD mode;

	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 (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 (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 = 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", (char *)NULL);
	    }
	    return TCL_ERROR;
	}
	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;
	}










	return TCL_OK;
    }

    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
 *	(by calling Tcl_BadChannelOption).
 *
 *----------------------------------------------------------------------
 */

static int
ConsoleGetOptionProc(
    ClientData 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;
    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 (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 (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;

	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);


    }

    if (valid) {
	return TCL_OK;
    }
    if (infoPtr->flags & CONSOLE_READ_OPS) {
	return Tcl_BadChannelOption(interp, optionName, "inputmode winsize");
    } else {
	return Tcl_BadChannelOption(interp, optionName, "");
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|




|

















|







|
|

















<
|
|
|
|
|
|
>
>
|
>
|
|

|
|
>
|
|
|
|
|
|
|
|
>
|
|
|
|
|
|
>
>





|
|

|










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(
    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). */
{
    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 (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(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");
	    }
	}

    } 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(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 (chanInfoPtr->flags & CONSOLE_READ_OPS) {
	return Tcl_BadChannelOption(interp, optionName, "inputmode");
    } else {
	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
 */

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_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)

















/*
 * Forward declarations for functions defined later 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);







|










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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.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

/*
 * 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
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_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);





#ifdef __cplusplus
}
#endif

/*
 *----------------------------------------------------------------------
 *







|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





>
>
>
>
>







126
127
128
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, Tcl_Size objc,
			    Tcl_Obj *const objv[]);






























#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
 *----------------------------------------------------------------------
 */

int
Dde_Init(
    Tcl_Interp *interp)
{
    if (!Tcl_InitStubs(interp, "8.5", 0)) {
	return TCL_ERROR;
    }

    Tcl_CreateObjCommand(interp, "dde", DdeObjCmd, NULL, NULL);
    Tcl_CreateExitHandler(DdeExitProc, NULL);
    return Tcl_PkgProvideEx(interp, TCL_DDE_PACKAGE_NAME, TCL_DDE_VERSION, NULL);
}









/*
 *----------------------------------------------------------------------
 *
 * Dde_SafeInit --
 *
 *	This function initializes the dde command within a safe interp







|



|



>
>
>
>
>
>
>
>







163
164
165
166
167
168
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)) {
	return TCL_ERROR;
    }

    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
{
    int result = Dde_Init(interp);
    if (result == TCL_OK) {
	Tcl_HideCommand(interp, "dde", "dde");
    }
    return result;
}









/*
 *----------------------------------------------------------------------
 *
 * Initialize --
 *
 *	Initialize the global DDE instance.







>
>
>
>
>
>
>
>







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
    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;
    RegisteredInterp *riPtr, *prevPtr;
    Tcl_DString dString;
    const WCHAR *actualName;
    Tcl_Obj *srvListPtr = NULL, **srvPtrPtr = NULL;

    int n, srvCount = 0, 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.
     */







|




>
|







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;
    RegisteredInterp *riPtr, *prevPtr;
    Tcl_DString dString;
    const WCHAR *actualName;
    Tcl_Obj *srvListPtr = NULL, **srvPtrPtr = NULL;
    Tcl_Size n, srvCount = 0, offset;
    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
    tsdPtr->interpListPtr = riPtr;
    wcscpy(riPtr->name, actualName);

    if (Tcl_IsSafe(interp)) {
	Tcl_ExposeCommand(interp, "dde", "dde");
    }

    Tcl_CreateObjCommand(interp, "dde", DdeObjCmd,
	    riPtr, DeleteProc);
    if (Tcl_IsSafe(interp)) {
	Tcl_HideCommand(interp, "dde", "dde");
    }
    Tcl_DStringFree(&dString);

    /*







|







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_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
    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);
	result = TCL_ERROR;
    }

    if (riPtr->handlerPtr != NULL) {
	/*
	 * Add the dde request data to the handler proc list.
	 */







|







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", (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
    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;
    DWORD dlen;
    WCHAR *utilString;
    Tcl_Obj *ddeObjectPtr;
    HDDEDATA ddeReturn = NULL;
    RegisteredInterp *riPtr;
    Conversation *convPtr, *prevConvPtr;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);







|







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;
    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
	    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);
		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,







|
<







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_GetStringFromObj(convPtr->returnPackagePtr, &len);

		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

		    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);
			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,







|
<







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_GetStringFromObj(variableObjPtr, &len);

			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
	}
	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.
	 */

	Tcl_Obj *returnPackagePtr;
	char *string;

	for (convPtr = tsdPtr->currentConversations; (convPtr != NULL)
		&& (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) {







|







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 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

	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 */
	    if (!string[dlen-1]) {
		dlen--;
	    }
	    ddeObjectPtr = Tcl_NewStringObj(string, dlen);
	} else {
	    /* 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);







|





|







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 */
	    if (!string[dlen-1]) {
		dlen--;
	    }
	    ddeObjectPtr = Tcl_NewStringObj(string, dlen);
	} else {
	    /* 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

    case XTYP_WILDCONNECT: {
	/*
	 * Dde wants a list of services and topics that we support.
	 */

	HSZPAIR *returnPtr;
	int i;
	int numItems;

	for (i = 0, riPtr = tsdPtr->interpListPtr; riPtr != NULL;
		i++, riPtr = riPtr->nextPtr) {
	    /*
	     * Empty loop body.
	     */
	}




	numItems = i;
	ddeReturn = DdeCreateDataHandle(ddeInstance, NULL,
		(numItems + 1) * sizeof(HSZPAIR), 0, 0, 0, 0);
	returnPtr = (HSZPAIR *) DdeAccessData(ddeReturn, &dlen);
	len = dlen;
	for (i = 0, riPtr = tsdPtr->interpListPtr; i < 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;







|
|








>
>
>
|

|


|







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;
	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 = (DWORD)i;
	ddeReturn = DdeCreateDataHandle(ddeInstance, NULL,
		(numItems + 1) * (DWORD)sizeof(HSZPAIR), 0, 0, 0, 0);
	returnPtr = (HSZPAIR *) DdeAccessData(ddeReturn, &dlen);
	len = dlen;
	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
	    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);
	}
	return TCL_ERROR;
    }

    *ddeConvPtr = ddeConv;
    return TCL_OK;
}







|







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", (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
	break;
    default:
	errorMessage = "dde command failed";
	errorCode = "FAILED";
    }

    Tcl_SetObjResult(interp, Tcl_NewStringObj(errorMessage, -1));
    Tcl_SetErrorCode(interp, "TCL", "DDE", errorCode, NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * DdeObjCmd --
 *







|







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, (char *)NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * DdeObjCmd --
 *
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
 *----------------------------------------------------------------------
 */

static int
DdeObjCmd(
    void *dummy,	/* Not used. */
    Tcl_Interp *interp,		/* The interp we are sending from */
    int objc,			/* Number of arguments */
    Tcl_Obj *const *objv)	/* The arguments */
{
    static const char *const ddeCommands[] = {
	"servername", "execute", "poke", "request", "services", "eval",
	(char *) NULL};
    enum DdeSubcommands {
	DDE_SERVERNAME, DDE_EXECUTE, DDE_POKE, DDE_REQUEST, DDE_SERVICES,
	DDE_EVAL
    };
    static const char *const ddeSrvOptions[] = {
	"-force", "-handler", "--", NULL
    };







|



|
<







1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312

1313
1314
1315
1316
1317
1318
1319
 *----------------------------------------------------------------------
 */

static int
DdeObjCmd(
    void *dummy,	/* Not used. */
    Tcl_Interp *interp,		/* The interp we are sending from */
    Tcl_Size objc,			/* Number of arguments */
    Tcl_Obj *const *objv)	/* The arguments */
{
    static const char *const ddeCommands[] = {
	"servername", "execute", "poke", "request", "services", "eval", NULL};

    enum DdeSubcommands {
	DDE_SERVERNAME, DDE_EXECUTE, DDE_POKE, DDE_REQUEST, DDE_SERVICES,
	DDE_EVAL
    };
    static const char *const ddeSrvOptions[] = {
	"-force", "-handler", "--", NULL
    };
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
    static const char *const ddeEvalOptions[] = {
	"-async", NULL
    };
    static const char *const ddeReqOptions[] = {
	"-binary", NULL
    };

    int index, i, argIndex;
    size_t length;
    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;







|
|







1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
    static const char *const ddeEvalOptions[] = {
	"-async", NULL
    };
    static const char *const ddeReqOptions[] = {
	"-binary", NULL
    };

    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
	    break;
	}
    }

    Initialize();

    if (firstArg != 1) {
	const char *src = Tcl_GetString(objv[firstArg]);

	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]);

	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,







|

<
















|

<







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_GetStringFromObj(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_GetStringFromObj(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
	    Tcl_DStringFree(&dsBuf);
	} else {
	    Tcl_ResetResult(interp);
	}
	break;

    case DDE_EXECUTE: {
	size_t dataLength;
	const void *dataString;
	Tcl_DString dsBuf;

	Tcl_DStringInit(&dsBuf);
	if (flags & DDE_FLAG_BINARY) {
	    dataString =
		    getByteArrayFromObj(objv[firstArg + 2], &dataLength);
	} else {
	    const char *src;

	    src = Tcl_GetString(objv[firstArg + 2]);
	    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);
	    result = TCL_ERROR;
	    break;
	}
	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);








|






|



|
<










|







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: {
	Tcl_Size dataLength;
	const void *dataString;
	Tcl_DString dsBuf;

	Tcl_DStringInit(&dsBuf);
	if (flags & DDE_FLAG_BINARY) {
	    dataString =
		    Tcl_GetByteArrayFromObj(objv[firstArg + 2], &dataLength);
	} else {
	    const char *src;

	    src = Tcl_GetStringFromObj(objv[firstArg + 2], &dataLength);

	    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", (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
	Tcl_DStringFree(&dsBuf);
	break;
    }
    case DDE_REQUEST: {
	const WCHAR *itemString;
	const char *src;

	src = Tcl_GetString(objv[firstArg + 2]);
	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);
	    result = TCL_ERROR;
	    goto cleanup;
	}
	hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL);
	DdeFreeStringHandle(ddeInstance, ddeService);
	DdeFreeStringHandle(ddeInstance, ddeTopic);








|
<







|







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_GetStringFromObj(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", (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
			returnObjPtr =
				Tcl_NewByteArrayObj((BYTE *) dataString, tmp);
		    } else {
			Tcl_DString dsBuf;

			if ((tmp >= sizeof(WCHAR))
				&& !dataString[tmp / sizeof(WCHAR) - 1]) {
			    tmp -= sizeof(WCHAR);
			}
			Tcl_DStringInit(&dsBuf);
			Tcl_WCharToUtfDString(dataString, tmp>>1, &dsBuf);
			returnObjPtr =
			    Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
				    Tcl_DStringLength(&dsBuf));
			Tcl_DStringFree(&dsBuf);







|







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 -= (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
    }
    case DDE_POKE: {
	Tcl_DString dsBuf;
	const WCHAR *itemString;
	BYTE *dataString;
	const char *src;

	src = Tcl_GetString(objv[firstArg + 2]);
	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);
	    result = TCL_ERROR;
	    goto cleanup;
	}
	Tcl_DStringInit(&dsBuf);
	if (flags & DDE_FLAG_BINARY) {
	    dataString = (BYTE *)
		    getByteArrayFromObj(objv[firstArg + 3], &length);
	} else {
	    const char *data =
		    Tcl_GetString(objv[firstArg + 3]);
	    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);







|
<






|






|


|
<







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_GetStringFromObj(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", (char *)NULL);
	    result = TCL_ERROR;
	    goto cleanup;
	}
	Tcl_DStringInit(&dsBuf);
	if (flags & DDE_FLAG_BINARY) {
	    dataString = (BYTE *)
		    Tcl_GetByteArrayFromObj(objv[firstArg + 3], &length);
	} else {
	    const char *data =
		    Tcl_GetStringFromObj(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
    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);
	    result = TCL_ERROR;
	    goto cleanup;
	}

	objc -= firstArg + 1;
	objv += firstArg + 1;








|







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", (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
	     */

	    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);
		result = TCL_ERROR;
	    }

	    if (result == TCL_OK) {
		if (objc == 1)
		    objPtr = objv[0];
		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));







|




|

|







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",
			(char *)NULL);
		result = TCL_ERROR;
	    }

	    if (result == TCL_OK) {
		if (objc == 1) {
		    objPtr = objv[0];
		} 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
	     * 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);
		result = TCL_ERROR;
		goto cleanup;
	    }

	    objPtr = Tcl_ConcatObj(objc, objv);
	    string = Tcl_GetString(objPtr);
	    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);







|





|
<







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", (char *)NULL);
		result = TCL_ERROR;
		goto cleanup;
	    }

	    objPtr = Tcl_ConcatObj(objc, objv);
	    string = Tcl_GetStringFromObj(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
		 * 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)) {
		    length -= sizeof(WCHAR);
		}
		Tcl_DStringInit(&dsBuf);
		Tcl_WCharToUtfDString(ddeDataString, length>>1, &dsBuf);
		resultPtr = Tcl_NewStringObj(Tcl_DStringValue(&dsBuf),
			Tcl_DStringLength(&dsBuf));
		Tcl_DStringFree(&dsBuf);







|







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 > (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
/*
 * tclWinError.c --
 *
 *	This file contains code for converting from Win32 errors to errno
 *	errors.
 *
 * Copyright (c) 1995-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.
 */

#include "tclInt.h"
/*






|







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 © 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
    ESTALE,		/* WSAESTALE */
    EREMOTE		/* WSAEREMOTE */
};

/*
 *----------------------------------------------------------------------
 *
 * TclWinConvertError --
 *
 *	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. */
{
    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]);







|













|
|







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 */
};

/*
 *----------------------------------------------------------------------
 *
 * Tcl_WinConvertError --
 *
 *	This routine converts a Win32 error into an errno value.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Sets the errno global variable.
 *
 *----------------------------------------------------------------------
 */

void
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]);
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");
	}
	vfprintf(stderr, format, argList);
	fprintf(stderr, "\n");
	fflush(stderr);
    }
}
#endif







|







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");
	}
	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
/*
 * tclWinFCmd.c
 *
 *	This file implements the Windows specific portion of file manipulation
 *	subcommands of the "file" command.
 *
 * Copyright (c) 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"







|







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 © 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"

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

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
};

const TclFileAttrProcs tclpFileAttrProcs[] = {
	{GetWinFileAttributes, SetWinFileAttributes},
	{GetWinFileAttributes, SetWinFileAttributes},
	{GetWinFileLongName, CannotSetAttribute},
	{GetWinFileAttributes, SetWinFileAttributes},







|







52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

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", 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
#endif
#endif

    if (retval != -1) {
	return retval;
    }

    TclWinConvertError(GetLastError());

    srcAttr = GetFileAttributesW(nativeSrc);
    dstAttr = GetFileAttributesW(nativeDst);
    if (srcAttr == 0xFFFFFFFF) {
	if (GetFullPathNameW(nativeSrc, 0, NULL,
		NULL) >= MAX_PATH) {
	    errno = ENAMETOOLONG;







|







275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
#endif
#endif

    if (retval != -1) {
	return retval;
    }

    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
	return TCL_ERROR;
    }
    if (errno == EACCES) {
    decode:
	if (srcAttr & FILE_ATTRIBUTE_DIRECTORY) {
	    WCHAR *nativeSrcRest, *nativeDstRest;
	    const char **srcArgv, **dstArgv;

	    int 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);

	    /*
	     * 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
	     */








>
|




















|
|







305
306
307
308
309
310
311
312
313
314
315
316
317
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
	return TCL_ERROR;
    }
    if (errno == EACCES) {
    decode:
	if (srcAttr & FILE_ATTRIBUTE_DIRECTORY) {
	    WCHAR *nativeSrcRest, *nativeDstRest;
	    const char **srcArgv, **dstArgv;
	    size_t size;
	    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, 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
		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,
			    nativeDst) != FALSE) {
			return TCL_OK;
		    }

		    /*
		     * Some new error has occurred. Don't know what it could
		     * be, but report this one.
		     */

		    TclWinConvertError(GetLastError());
		    CreateDirectoryW(nativeDst, NULL);
		    SetFileAttributesW(nativeDst, dstAttr);
		    if (Tcl_GetErrno() == EACCES) {
			/*
			 * Decode the EACCES to a more meaningful error.
			 */








|
<








|







407
408
409
410
411
412
413
414

415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
		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, nativeDst) != FALSE) {

			return TCL_OK;
		    }

		    /*
		     * Some new error has occurred. Don't know what it could
		     * be, but report this one.
		     */

		    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
		    }

		    /*
		     * Can't backup dst file or move src file. Return that
		     * error. Could happen if an open file refers to dst.
		     */

		    TclWinConvertError(GetLastError());
		    if (Tcl_GetErrno() == EACCES) {
			/*
			 * Decode the EACCES to a more meaningful error.
			 */

			goto decode;
		    }







|







484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
		    }

		    /*
		     * Can't backup dst file or move src file. Return that
		     * error. Could happen if an open file refers to dst.
		     */

		    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
#endif
#endif

    if (retval != -1) {
	return retval;
    }

    TclWinConvertError(GetLastError());
    if (Tcl_GetErrno() == EBADF) {
	Tcl_SetErrno(EACCES);
	return TCL_ERROR;
    }
    if (Tcl_GetErrno() == EACCES) {
	DWORD srcAttr, dstAttr;








|







665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
#endif
#endif

    if (retval != -1) {
	return retval;
    }

    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
		    }
		}
		Tcl_SetErrno(EISDIR);
	    }
	    if (dstAttr & FILE_ATTRIBUTE_READONLY) {
		SetFileAttributesW(nativeDst,
			dstAttr & ~((DWORD)FILE_ATTRIBUTE_READONLY));
		if (CopyFileW(nativeSrc, nativeDst,
			0) != FALSE) {
		    return TCL_OK;
		}

		/*
		 * Still can't copy onto dst. Return that error, and restore
		 * attributes of dst.
		 */

		TclWinConvertError(GetLastError());
		SetFileAttributesW(nativeDst, dstAttr);
	    }
	}
    }
    return TCL_ERROR;
}








|
<








|







692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
		    }
		}
		Tcl_SetErrno(EISDIR);
	    }
	    if (dstAttr & FILE_ATTRIBUTE_READONLY) {
		SetFileAttributesW(nativeDst,
			dstAttr & ~((DWORD)FILE_ATTRIBUTE_READONLY));
		if (CopyFileW(nativeSrc, nativeDst, 0) != FALSE) {

		    return TCL_OK;
		}

		/*
		 * Still can't copy onto dst. Return that error, and restore
		 * attributes of dst.
		 */

		Tcl_WinConvertError(GetLastError());
		SetFileAttributesW(nativeDst, dstAttr);
	    }
	}
    }
    return TCL_ERROR;
}

762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
	Tcl_SetErrno(ENOENT);
	return TCL_ERROR;
    }

    if (DeleteFileW(path) != FALSE) {
	return TCL_OK;
    }
    TclWinConvertError(GetLastError());

    if (Tcl_GetErrno() == EACCES) {
	attr = GetFileAttributesW(path);
	if (attr != 0xFFFFFFFF) {
	    if (attr & FILE_ATTRIBUTE_DIRECTORY) {
		if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
		    /*







|







761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
	Tcl_SetErrno(ENOENT);
	return TCL_ERROR;
    }

    if (DeleteFileW(path) != FALSE) {
	return TCL_OK;
    }
    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
		 */

		Tcl_SetErrno(EISDIR);
	    } else if (attr & FILE_ATTRIBUTE_READONLY) {
		int res = SetFileAttributesW(path,
			attr & ~((DWORD) FILE_ATTRIBUTE_READONLY));

		if ((res != 0) &&
			(DeleteFileW(path) != FALSE)) {
		    return TCL_OK;
		}
		TclWinConvertError(GetLastError());
		if (res != 0) {
		    SetFileAttributesW(path, attr);
		}
	    }
	}
    } else if (Tcl_GetErrno() == ENOENT) {
	attr = GetFileAttributesW(path);







<
|


|







788
789
790
791
792
793
794

795
796
797
798
799
800
801
802
803
804
805
		 */

		Tcl_SetErrno(EISDIR);
	    } else if (attr & FILE_ATTRIBUTE_READONLY) {
		int res = SetFileAttributesW(path,
			attr & ~((DWORD) FILE_ATTRIBUTE_READONLY));


		if ((res != 0) && (DeleteFileW(path) != FALSE)) {
		    return TCL_OK;
		}
		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
static int
DoCreateDirectory(
    const WCHAR *nativePath)	/* Pathname of directory to create (native). */
{
    if (CreateDirectoryW(nativePath, NULL) == 0) {
	DWORD error = GetLastError();

	TclWinConvertError(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.
 *
 * 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.







|












|







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 int
DoCreateDirectory(
    const WCHAR *nativePath)	/* Pathname of directory to create (native). */
{
    if (CreateDirectoryW(nativePath, NULL) == 0) {
	DWORD error = GetLastError();

	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 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
    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);

    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);
	}
	Tcl_DStringFree(&ds);
	Tcl_IncrRefCount(*errorPtr);
    }
    return ret;
}








|
|












|







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
    normDestPtr = Tcl_FSGetNormalizedPath(NULL,destPathPtr);
    if ((normSrcPtr == NULL) || (normDestPtr == NULL)) {
	return TCL_ERROR;
    }

    Tcl_DStringInit(&srcString);
    Tcl_DStringInit(&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), TCL_INDEX_NONE);
	}
	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

	Tcl_DString native;
	normPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
	if (normPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_DStringInit(&native);
	Tcl_UtfToWCharDString(TclGetString(normPtr), -1, &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);
	    }
	    Tcl_IncrRefCount(*errorPtr);
	}
	Tcl_DStringFree(&ds);
    }

    return ret;







|












|







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

	Tcl_DString native;
	normPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
	if (normPtr == NULL) {
	    return TCL_ERROR;
	}
	Tcl_DStringInit(&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 = 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
	 */

	if (RemoveDirectoryW(nativePath) != FALSE) {
	    return TCL_OK;
	}
    }

    TclWinConvertError(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







|







1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
	 */

	if (RemoveDirectoryW(nativePath) != FALSE) {
	    return TCL_OK;
	}
    }

    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
		if (TclWinSymLinkDelete(nativePath, 1) != 0) {
		    goto end;
		}
	    }

	    if (attr & FILE_ATTRIBUTE_READONLY) {
		attr &= ~FILE_ATTRIBUTE_READONLY;
		if (SetFileAttributesW(nativePath,
			attr) == FALSE) {
		    goto end;
		}
		if (RemoveDirectoryW(nativePath) != FALSE) {
		    return TCL_OK;
		}
		TclWinConvertError(GetLastError());
		SetFileAttributesW(nativePath,
			attr | FILE_ATTRIBUTE_READONLY);
	    }
	}
    }

    if (Tcl_GetErrno() == ENOTEMPTY) {







|
<





|







1075
1076
1077
1078
1079
1080
1081
1082

1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
		if (TclWinSymLinkDelete(nativePath, 1) != 0) {
		    goto end;
		}
	    }

	    if (attr & FILE_ATTRIBUTE_READONLY) {
		attr &= ~FILE_ATTRIBUTE_READONLY;
		if (SetFileAttributesW(nativePath, attr) == FALSE) {

		    goto end;
		}
		if (RemoveDirectoryW(nativePath) != FALSE) {
		    return TCL_OK;
		}
		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
    }

  end:
    if (errorPtr != NULL) {
	char *p;

	Tcl_DStringInit(errorPtr);
	p = Tcl_WCharToUtfDString(nativePath, -1, errorPtr);
	for (; *p; ++p) {
	    if (*p == '\\') *p = '/';


	}
    }
    return TCL_ERROR;

}

static int







|

|
>
>







1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
    }

  end:
    if (errorPtr != NULL) {
	char *p;

	Tcl_DStringInit(errorPtr);
	p = Tcl_WCharToUtfDString(nativePath, TCL_INDEX_NONE, errorPtr);
	for (; *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
    nativeSource = (WCHAR *) Tcl_DStringValue(sourcePtr);
    handle = FindFirstFileW(nativeSource, &data);
    if (handle == INVALID_HANDLE_VALUE) {
	/*
	 * Can't read directory.
	 */

	TclWinConvertError(GetLastError());
	nativeErrfile = nativeSource;
	goto end;
    }

    Tcl_DStringSetLength(sourcePtr, oldSourceLen + 1);
    Tcl_DStringSetLength(sourcePtr, oldSourceLen);
    result = traverseProc(nativeSource, nativeTarget, DOTREE_PRED,







|







1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
    nativeSource = (WCHAR *) Tcl_DStringValue(sourcePtr);
    handle = FindFirstFileW(nativeSource, &data);
    if (handle == INVALID_HANDLE_VALUE) {
	/*
	 * Can't read directory.
	 */

	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
	result = traverseProc((const WCHAR *)Tcl_DStringValue(sourcePtr),
		(const WCHAR *)(targetPtr == NULL ? NULL : Tcl_DStringValue(targetPtr)),
		DOTREE_POSTD, errorPtr);
    }

  end:
    if (nativeErrfile != NULL) {
	TclWinConvertError(GetLastError());
	if (errorPtr != NULL) {
	    Tcl_DStringInit(errorPtr);
	    Tcl_WCharToUtfDString(nativeErrfile, -1, errorPtr);
	}
	result = TCL_ERROR;
    }

    return result;
}








|


|







1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
	result = traverseProc((const WCHAR *)Tcl_DStringValue(sourcePtr),
		(const WCHAR *)(targetPtr == NULL ? NULL : Tcl_DStringValue(targetPtr)),
		DOTREE_POSTD, errorPtr);
    }

  end:
    if (nativeErrfile != NULL) {
	Tcl_WinConvertError(GetLastError());
	if (errorPtr != NULL) {
	    Tcl_DStringInit(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
	    return TCL_OK;
	}
	break;
    case DOTREE_PRED:
	if (DoCreateDirectory(nativeDst) == TCL_OK) {
	    DWORD attr = GetFileAttributesW(nativeSrc);

	    if (SetFileAttributesW(nativeDst,
		    attr) != FALSE) {
		return TCL_OK;
	    }
	    TclWinConvertError(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);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *







|
<


|













|







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
	    return TCL_OK;
	}
	break;
    case DOTREE_PRED:
	if (DoCreateDirectory(nativeDst) == TCL_OK) {
	    DWORD attr = GetFileAttributesW(nativeSrc);

	    if (SetFileAttributesW(nativeDst, attr) != FALSE) {

		return TCL_OK;
	    }
	    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, TCL_INDEX_NONE, errorPtr);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
	    return TCL_OK;
	}
	break;
    }

    if (errorPtr != NULL) {
	Tcl_DStringInit(errorPtr);
	Tcl_WCharToUtfDString(nativeSrc, -1, errorPtr);
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------
 *







|







1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
	    return TCL_OK;
	}
	break;
    }

    if (errorPtr != NULL) {
	Tcl_DStringInit(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

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_SetObjResult(interp, Tcl_ObjPrintf("could not read \"%s\": %s",
	    TclGetString(fileName), Tcl_PosixError(interp)));
}

/*
 *----------------------------------------------------------------------
 *







|







1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490

static void
StatError(
    Tcl_Interp *interp,		/* The interp that has the error */
    Tcl_Obj *fileName)		/* The name of the file which caused the
				 * error. */
{
    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
	 * 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;
	const char *str = TclGetStringFromObj(fileName, &len);

	if (len < 4) {
	    if (len == 0) {
		/*
		 * Not sure if this is possible, but we pass it on anyway.
		 */







|







1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
	 * 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.
	 */

	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
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_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",







|

<







1589
1590
1591
1592
1593
1594
1595
1596
1597

1598
1599
1600
1601
1602
1603
1604
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. */
{
    Tcl_Size pathc, i, length;
    Tcl_Obj *splitPath;


    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
	     * 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_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);
	    }
	    Tcl_ListObjReplace(NULL, splitPath, i, 1, 1, &tempPath);
	    FindClose(handle);
	}
    }

    *attributePtrPtr = Tcl_FSJoinPath(splitPath, -1);

    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







|


<
<
<
<
<
<
<
<
<
<
|
<
|




|







1705
1706
1707
1708
1709
1710
1711
1712
1713
1714










1715

1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
	     * about the second.
	     *
	     *	fprintf(stderr, "%d\n", data.w.cAlternateFileName[0]);
	     *	fprintf(stderr, "%d\n", ((WCHAR *) nativeName)[0]);
	     */

	    Tcl_DStringInit(&dsTemp);
	    Tcl_WCharToUtfDString(nativeName, TCL_INDEX_NONE, &dsTemp);
	    Tcl_DStringFree(&ds);











            tempPath = Tcl_DStringToObj(&dsTemp);

            Tcl_ListObjReplace(NULL, splitPath, i, 1, 1, &tempPath);
	    FindClose(handle);
	}
    }

    *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
	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);
		Tcl_ListObjAppendElement(NULL, resultPtr, elemPtr);
	    }
	}
    } else {
	for (p = buf; *p != '\0'; p += 4) {
	    p[2] = '/';
	    elemPtr = Tcl_NewStringObj(p, -1);
	    Tcl_ListObjAppendElement(NULL, resultPtr, elemPtr);
	}
    }

    Tcl_IncrRefCount(resultPtr);
    return resultPtr;
}







|






|







1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
	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, TCL_INDEX_NONE);
		Tcl_ListObjAppendElement(NULL, resultPtr, elemPtr);
	    }
	}
    } else {
	for (p = buf; *p != '\0'; p += 4) {
	    p[2] = '/';
	    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

    /*
     * Build the path in writable memory from the user-supplied pieces and
     * some defaults. First, the parent temporary directory.
     */

    if (dirObj) {
	Tcl_GetString(dirObj);
	if (dirObj->length < 1) {
	    goto useSystemTemp;
	}
	Tcl_DStringInit(&base);
	Tcl_UtfToWCharDString(Tcl_GetString(dirObj), -1, &base);
	if (dirObj->bytes[dirObj->length - 1] != '\\') {
	    Tcl_UtfToWCharDString("\\", -1, &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);
    } else {
	Tcl_UtfToWCharDString(DEFAULT_TEMP_DIR_PREFIX, -1, &base);
    }
    Tcl_UtfToWCharDString("_", -1, &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.
     */







|




|

|















|

|

|







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

    /*
     * Build the path in writable memory from the user-supplied pieces and
     * some defaults. First, the parent temporary directory.
     */

    if (dirObj) {
	TclGetString(dirObj);
	if (dirObj->length < 1) {
	    goto useSystemTemp;
	}
	Tcl_DStringInit(&base);
	Tcl_UtfToWCharDString(TclGetString(dirObj), TCL_INDEX_NONE, &base);
	if (dirObj->bytes[dirObj->length - 1] != '\\') {
	    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(TclGetString(basenameObj), TCL_INDEX_NONE, &base);
    } else {
	Tcl_UtfToWCharDString(DEFAULT_TEMP_DIR_PREFIX, TCL_INDEX_NONE, &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

	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);
    } 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_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_DStringFree(&base);
    return TclDStringToObj(&name);
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|









|










|

|









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

	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, 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) {
	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), TCL_INDEX_NONE, &name);
    Tcl_DStringFree(&base);
    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
/*
 * 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.
 *
 * 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"








|







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 © 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
#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)

/*
 * 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.
 */








|







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	\
	((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
    WCHAR dummyBuf[MAX_PATH * 3];
} DUMMY_REPARSE_BUFFER;

/*
 * Other typedefs required by this code.
 */

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 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, ...);







|




















|







145
146
147
148
149
150
151
152
153
154
155
156
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 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 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

    if (!GetFullPathNameW(linkTargetPath, MAX_PATH, tempFileName,
	    &tempFilePart)) {
	/*
	 * Invalid file.
	 */

	TclWinConvertError(GetLastError());
	return -1;
    }

    /*
     * Make sure source file doesn't exist.
     */








|







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219

    if (!GetFullPathNameW(linkTargetPath, MAX_PATH, tempFileName,
	    &tempFilePart)) {
	/*
	 * Invalid file.
	 */

	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

    if (!GetFullPathNameW(linkSourcePath, MAX_PATH, tempFileName,
	    &tempFilePart)) {
	/*
	 * Invalid file.
	 */

	TclWinConvertError(GetLastError());
	return -1;
    }

    /*
     * Check the target.
     */

    attr = GetFileAttributesW(linkTargetPath);
    if (attr == INVALID_FILE_ATTRIBUTES) {
	/*
	 * The target doesn't exist.
	 */

	TclWinConvertError(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());
	} else if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {


	    /*
	     * Can't symlink files.
	     */



	    Tcl_SetErrno(ENOTDIR);

	} else {
	    Tcl_SetErrno(ENODEV);
	}
    } else {
	/*
	 * We've got a directory. Now check whether what we're trying to do is
	 * reasonable.







|













|














|

>
>
|
|
|

>
>
|
>







229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
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.
	 */

	Tcl_WinConvertError(GetLastError());
	return -1;
    }

    /*
     * Check the target.
     */

    attr = GetFileAttributesW(linkTargetPath);
    if (attr == INVALID_FILE_ATTRIBUTES) {
	/*
	 * The target doesn't exist.
	 */

	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;
	    }

	    Tcl_WinConvertError(GetLastError());
	} else if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
	    if (CreateSymbolicLinkW(linkSourcePath, linkTargetPath,
		    0x2 /* SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE */)) {
		/*
		 * Success!
		 */

		return 0;
	    } else {
		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

    if (!GetFullPathNameW(linkSourcePath, MAX_PATH, tempFileName,
	    &tempFilePart)) {
	/*
	 * Invalid file.
	 */

	TclWinConvertError(GetLastError());
	return NULL;
    }

    /*
     * Make sure source file does exist.
     */

    attr = GetFileAttributesW(linkSourcePath);
    if (attr == INVALID_FILE_ATTRIBUTES) {
	/*
	 * The source doesn't exist.
	 */

	TclWinConvertError(GetLastError());
	return NULL;

    } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
	/*
	 * It is a file - this is not yet supported.
	 */








|













|







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.
	 */

	Tcl_WinConvertError(GetLastError());
	return NULL;
    }

    /*
     * Make sure source file does exist.
     */

    attr = GetFileAttributesW(linkSourcePath);
    if (attr == INVALID_FILE_ATTRIBUTES) {
	/*
	 * The source doesn't exist.
	 */

	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
    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());
	    CloseHandle(hFile);
	} else {
	    CloseHandle(hFile);
	    if (!linkOnly) {
		RemoveDirectoryW(linkOrigPath);
	    }
	    return 0;







|







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.
	     */

	    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
	    FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);

    if (hFile == INVALID_HANDLE_VALUE) {
	/*
	 * Error creating directory.
	 */

	TclWinConvertError(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());
	CloseHandle(hFile);
	return -1;
    }
    CloseHandle(hFile);

    if (!IsReparseTagValid(buffer->ReparseTag)) {
	Tcl_SetErrno(EINVAL);







|













|







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.
	 */

	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.
	 */

	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
     */

    if (CreateDirectoryW(linkDirPath, NULL) == 0) {
	/*
	 * Error creating directory.
	 */

	TclWinConvertError(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());
	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());
	CloseHandle(hFile);
	RemoveDirectoryW(linkDirPath);
	return -1;
    }
    CloseHandle(hFile);

    /*







|










|














|







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.
	 */

	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.
	 */

	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.
	 */

	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
    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);
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, sizeof(name), NULL, NULL);
    TclWinNoBackslash(name);
    TclSetObjNameOfExecutable(Tcl_NewStringObj(name, -1), NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * TclpMatchInDirectory --
 *







|


|







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, sizeof(wName)/sizeof(WCHAR));
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, name, sizeof(name), NULL, NULL);
    TclWinNoBackslash(name);
    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
	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);

	    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)) {
		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;
	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;








|
|









|










|







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;
	    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, 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. */
	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
	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)) {
	    return TCL_OK;
	}

	/*
	 * Build up the directory name for searching, including a trailing
	 * directory separator.
	 */







|







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)) {
	    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
	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);
	} else {
	    dirName = TclDStringAppendLiteral(&dsOrig, "*.*");
	}

	Tcl_DStringInit(&ds);
	native = Tcl_UtfToWCharDString(dirName, -1, &ds);
	if ((types == NULL) || (types->type != TCL_GLOB_TYPE_DIR)) {
	    handle = FindFirstFileW(native, &data);
	} else {
	    /*
	     * We can be more efficient, for pure directory requests.
	     */








|





|







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, TCL_INDEX_NONE);
	} else {
	    dirName = TclDStringAppendLiteral(&dsOrig, "*.*");
	}

	Tcl_DStringInit(&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
		 * means we just return TCL_OK, indicating no results found.
		 */

		Tcl_DStringFree(&dsOrig);
		return TCL_OK;
	    }

	    TclWinConvertError(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;







|







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;
	    }

	    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
	do {
	    const char *utfname;
	    int checkDrive = 0, isDrive;

	    native = data.cFileName;
	    attr = data.dwFileAttributes;
	    Tcl_DStringInit(&ds);
	    utfname = Tcl_WCharToUtfDString(native, -1, &ds);

	    if (!matchSpecialDots) {
		/*
		 * If it is exactly '.' or '..' then we ignore it.
		 */

		if ((utfname[0] == '.') && (utfname[1] == '\0'







|







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, 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

/*
 * 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
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') {
		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') {
		return 4;
	    }
	}

    } else if (!strcasecmp(path, "prn") || !strcasecmp(path, "nul")
	    || !strcasecmp(path, "aux")) {
	/*







|













|




















|







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 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') {
		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') {
		return 4;
	    }
	}

    } else if (!strcasecmp(path, "prn") || !strcasecmp(path, "nul")
	    || !strcasecmp(path, "aux")) {
	/*
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
    Tcl_DStringInit(bufferPtr);

    wDomain = NULL;
    domain = Tcl_UtfFindFirst(name, '@');
    if (domain == NULL) {
	const char *ptr;

	/*
	 * No domain. Firstly check it's the current user










	 */




	ptr = TclpGetUserName(&ds);
	if (ptr != NULL && strcasecmp(name, ptr) == 0) {
	    /*



	     * Try safest and fastest way to get current user home
	     */

	    ptr = TclGetEnv("HOME", &ds);
	    if (ptr != NULL) {


		Tcl_JoinPath(1, &ptr, bufferPtr);

		rc = 1;
		result = Tcl_DStringValue(bufferPtr);



	    }
	}
	Tcl_DStringFree(&ds);
    } else {
	Tcl_DStringInit(&ds);
	wName = Tcl_UtfToWCharDString(domain + 1, -1, &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);







|
|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>


<
>
>
>
|
<
|
<
|
>
>
|
>
|
<
>
>
>





|







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
    Tcl_DStringInit(bufferPtr);

    wDomain = NULL;
    domain = Tcl_UtfFindFirst(name, '@');
    if (domain == NULL) {
	const char *ptr;

        /*
         * 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 [email protected], 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) {

	    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 */

	    if (hProcess) {
		HANDLE hToken;
		if (OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
		    if (GetUserProfileDirectoryW(hToken, buf, &nChars)) {
			result = Tcl_WCharToUtfDString(buf, nChars-1, (bufferPtr));
			rc = 1;

		    }
		    CloseHandle(hToken);
		}
	    }
	}
	Tcl_DStringFree(&ds);
    } else {
	Tcl_DStringInit(&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
	     */

	    for (i = 0; i < size; ++i) {
		if (result[i] == '\\') {
		    result[i] = '/';
		}
	    }
	    NetApiBufferFree((void *) uiPtr);
	}
	Tcl_DStringFree(&ds);
    }
    if (wDomain != NULL) {
	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;
}

/*
 *---------------------------------------------------------------------------







|




|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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);
	}
	Tcl_DStringFree(&ds);
    }
    if (wDomain != NULL) {
	NetApiBufferFree((void *)wDomain);
























    }

    return result;
}

/*
 *---------------------------------------------------------------------------
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
    if (attr == INVALID_FILE_ATTRIBUTES) {
	/*
	 * File might not exist.
	 */

	DWORD lasterror = GetLastError();
	if (lasterror != ERROR_SHARING_VIOLATION) {
	    TclWinConvertError(lasterror);
	    return -1;
	}
    }

    if (mode == F_OK) {
	/*
	 * File exists, nothing else to check.







|







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) {
	    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
	    if (GetLastError() == ERROR_ACCESS_DENIED) {
		Tcl_SetErrno(EACCES);
		return -1;
	    }
	}

	/*
	 * We cannnot 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.







|







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 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
	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);
	    return -1;
	}

	/*
	 * Now size contains the size of buffer needed.
	 */








|







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!
	     */

	    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

	    goto accessError;
	}

	RevertToSelf();

	/*
	 * Setup desiredAccess according to the access priveleges we are
	 * checking.
	 */

	if (mode & R_OK) {
	    desiredAccess |= FILE_GENERIC_READ;
	}
	if (mode & W_OK) {







|







1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790

	    goto accessError;
	}

	RevertToSelf();

	/*
	 * 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
		&genMap, &privSet, &privSetSize, &grantedAccess,
		&accessYesNo)) {
	    /*
	     * Unable to perform access check.
	     */

	accessError:
	    TclWinConvertError(GetLastError());
	    if (sdPtr != NULL) {
		HeapFree(GetProcessHeap(), 0, sdPtr);
	    }
	    if (hToken != NULL) {
		CloseHandle(hToken);
	    }
	    return -1;







|







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:
	    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
	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;
}

/*







<







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"bat") == 0)) {
	return 1;
    }
    return 0;
}

/*
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918

    if (!nativePath) {
	return -1;
    }
    result = SetCurrentDirectoryW(nativePath);

    if (result == 0) {
	TclWinConvertError(GetLastError());
	return -1;
    }
    return 0;
}

/*
 *----------------------------------------------------------------------







|







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) {
	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
				 * name of current directory. */
{
    WCHAR buffer[MAX_PATH];
    char *p;
    WCHAR *native;

    if (GetCurrentDirectoryW(MAX_PATH, buffer) == 0) {
	TclWinConvertError(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);

    /*
     * Convert to forward slashes for easier use in scripts.
     */

    for (p = Tcl_DStringValue(bufferPtr); *p != '\0'; p++) {
	if (*p == '\\') {







|


















|







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) {
	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, 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
    /*
     * 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
     * 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.
     */








|







2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
    /*
     * 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 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.
     */

2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
        } 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);

	/*
	 * 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.
	 */







|
|







2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
        } 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 = ((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
	if (GetFileAttributesExW(nativePath,
		GetFileExInfoStandard, &data) != TRUE) {
	    HANDLE hFind;
	    WIN32_FIND_DATAW ffd;
	    DWORD lasterror = GetLastError();

	    if (lasterror != ERROR_SHARING_VIOLATION) {
		TclWinConvertError(lasterror);
		return -1;
		}
	    hFind = FindFirstFileW(nativePath, &ffd);
	    if (hFind == INVALID_HANDLE_VALUE) {
		TclWinConvertError(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_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));







|




|








|
|







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
	if (GetFileAttributesExW(nativePath,
		GetFileExInfoStandard, &data) != TRUE) {
	    HANDLE hFind;
	    WIN32_FIND_DATAW ffd;
	    DWORD lasterror = GetLastError();

	    if (lasterror != ERROR_SHARING_VIOLATION) {
		Tcl_WinConvertError(lasterror);
		return -1;
		}
	    hFind = FindFirstFileW(nativePath, &ffd);
	    if (hFind == INVALID_HANDLE_VALUE) {
		Tcl_WinConvertError(GetLastError());
		return -1;
	    }
	    memcpy(&data, &ffd, sizeof(data));
	    FindClose(hFind);
	}

	attr = data.dwFileAttributes;

	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));
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
    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);

    if ((fullPath[0] == '\\') && (fullPath[1] == '\\')) {
	const char *p;
	DWORD dw;
	const WCHAR *nativeVol;
	Tcl_DString volString;








|







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, 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
{
    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);
}

/*
 *------------------------------------------------------------------------
 *
 * FromCTime --
 *







|







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 -
	    (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
 *	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
 *	codes to determine the cause of the problem.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

ClientData
TclpGetNativeCwd(
    ClientData clientData)
{
    WCHAR buffer[MAX_PATH];

    if (GetCurrentDirectoryW(MAX_PATH, buffer) == 0) {
	TclWinConvertError(GetLastError());
	return NULL;
    }

    if (clientData != NULL) {
	if (wcscmp((const WCHAR *) clientData, buffer) == 0) {
	    return clientData;
	}







|








|

|




|







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
 *	codes to determine the cause of the problem.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpGetNativeCwd(
    void *clientData)
{
    WCHAR buffer[MAX_PATH];

    if (GetCurrentDirectoryW(MAX_PATH, buffer) == 0) {
	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
	return NULL;
    }
    path = TclGetString(normPath);
    if (path == NULL) {
	return NULL;
    }

    firstSeparator = strchr(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);
    }
#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







|


















|
|







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((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, 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
	    if (GetFileAttributesExW(nativePath,
		    GetFileExInfoStandard, &data) != TRUE) {
		/*
		 * File doesn't exist.
		 */

		if (isDrive) {
		    int len = WinIsReserved(path);

		    if (len > 0) {
			/*
			 * Actually it does exist - COM1, etc.
			 */

			int i;

			for (i=0 ; i<len ; 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));
			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]
			 */







|






|


|








|







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) {
		    size_t len = WinIsReserved(path);

		    if (len > 0) {
			/*
			 * Actually it does exist - COM1, etc.
			 */

			size_t i;

			for (i=0 ; i<len ; i++) {
			    WCHAR wc = ((WCHAR *)nativePath)[i];

			    if (wc >= 'a') {
				wc -= ('a' - 'A');
				((WCHAR *) nativePath)[i] = wc;
			    }
			}
			Tcl_DStringAppend(&dsNorm,
				(const char *)nativePath,
				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
		     * Tcl_GetStringFromObj(to, &pathLen);
		     * nextCheckpoint = pathLen;
		     *
		     * So, instead we have to start from the beginning.
		     */

		    nextCheckpoint = 0;
		    Tcl_AppendToObj(to, currentPathEndPosition, -1);

		    /*
		     * Convert link to forward slashes.
		     */

		    for (path = TclGetString(to); *path != 0; path++) {
			if (*path == '\\') {







|







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, 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
			    nativeName = fData.cAlternateFileName;
			}
			FindClose(handle);
			Tcl_DStringAppend(&dsNorm, (const char *) L"/",
				sizeof(WCHAR));
			Tcl_DStringAppend(&dsNorm,
				(const char *) nativeName,
				(int) (wcslen(nativeName)*sizeof(WCHAR)));
		    }
		}
	    }
#endif /* !TclNORM_LONG_PATH */
	    Tcl_DStringFree(&ds);
	    lastValidPathEnd = currentPathEndPosition;
	    if (cur == 0) {







|







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,
				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
	currentPathEndPosition++;

#ifdef TclNORM_LONG_PATH
	/*
	 * Convert the entire known path to long form.
	 */

	if (1) {
	    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.
	     */

	    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.
     */








<
|
|
|

|
|
|
|
|
|
|
|

|
|
|
|
|
|
<







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.
	 */


	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.
	 */

	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
	nextCheckpoint = Tcl_DStringLength(&ds);
	if (*lastValidPathEnd != 0) {
	    /*
	     * Not the end of the string.
	     */

	    Tcl_Obj *tmpPathPtr;
	    size_t length;

	    tmpPathPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),
		    nextCheckpoint);
	    Tcl_AppendToObj(tmpPathPtr, lastValidPathEnd, -1);
	    path = TclGetStringFromObj(tmpPathPtr, &length);
	    Tcl_SetStringObj(pathPtr, path, length);
	    Tcl_DecrRefCount(tmpPathPtr);
	} else {
	    /*
	     * End of string was reached above.
	     */

	    Tcl_SetStringObj(pathPtr, Tcl_DStringValue(&ds), nextCheckpoint);







|



|
|
|







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;
	    Tcl_Size len;

	    tmpPathPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),
		    nextCheckpoint);
	    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
	 * 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_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;
	const char *drive = TclGetStringFromObj(useThisCwd, &cwdLen);
	char drive_cur = path[0];

	if (drive_cur >= 'a') {
	    drive_cur -= ('a' - 'A');
	}
	if (drive[0] == drive_cur) {







|











|







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, 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.
	 */

	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
	     * 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);
    }
    *useThisCwdPtr = useThisCwd;
    return absolutePath;
}

/*
 *---------------------------------------------------------------------------







|







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, 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
 *	None.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclpNativeToNormalized(
    ClientData clientData)
{
    Tcl_DString ds;
    Tcl_Obj *objPtr;
    size_t len;
    char *copy, *p;

    Tcl_DStringInit(&ds);
    Tcl_WCharToUtfDString((const WCHAR *) clientData, -1, &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.







|







|







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(
    void *clientData)
{
    Tcl_DString ds;
    Tcl_Obj *objPtr;
    size_t len;
    char *copy, *p;

    Tcl_DStringInit(&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
 *
 * Side effects:
 *	Memory will be allocated. The path might be normalized.
 *
 *---------------------------------------------------------------------------
 */

ClientData
TclNativeCreateNativeRep(
    Tcl_Obj *pathPtr)
{
    WCHAR *nativePathPtr = NULL;
    const char *str;
    Tcl_Obj *validPathPtr;
    size_t len;
    WCHAR *wp;

    if (TclFSCwdIsNative()) {
	/*
	 * The cwd is native, which means we can use the translated path
	 * without worrying about normalization (this will also usually be
	 * shorter so the utf-to-external conversion will be somewhat faster).







|






|







3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
 *
 * Side effects:
 *	Memory will be allocated. The path might be normalized.
 *
 *---------------------------------------------------------------------------
 */

void *
TclNativeCreateNativeRep(
    Tcl_Obj *pathPtr)
{
    WCHAR *nativePathPtr = NULL;
    const char *str;
    Tcl_Obj *validPathPtr;
    Tcl_Size len;
    WCHAR *wp;

    if (TclFSCwdIsNative()) {
	/*
	 * The cwd is native, which means we can use the translated path
	 * without worrying about normalization (this will also usually be
	 * shorter so the utf-to-external conversion will be somewhat faster).
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
	 */

	Tcl_IncrRefCount(validPathPtr);
    }

    str = TclGetStringFromObj(validPathPtr, &len);

    if (strlen(str) != len) {
	/*
	 * String contains NUL-bytes. This is invalid.
	 */

	goto done;
    }








|







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) != (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

    /*
     * Overallocate 6 chars, making some room for extended paths
     */

    wp = nativePathPtr = (WCHAR *)Tcl_Alloc((len + 6) * sizeof(WCHAR));
    if (nativePathPtr==0) {
      goto done;
    }
    MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, nativePathPtr,
	    len + 1);


    /*
     * 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>
     */

    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));







|


|
>

















|







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;
    }
    MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, nativePathPtr,
	    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:
     * <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));
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
 *
 * Side effects:
 *	Memory allocation for the copy.
 *
 *---------------------------------------------------------------------------
 */

ClientData
TclNativeDupInternalRep(
    ClientData clientData)
{
    char *copy;
    size_t len;

    if (clientData == NULL) {
	return NULL;
    }







|

|







3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
 *
 * Side effects:
 *	Memory allocation for the copy.
 *
 *---------------------------------------------------------------------------
 */

void *
TclNativeDupInternalRep(
    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
     */

    fileHandle = CreateFileW(native, FILE_WRITE_ATTRIBUTES, 0, NULL,
	    OPEN_EXISTING, flags, NULL);

    if (fileHandle == INVALID_HANDLE_VALUE ||
	    !SetFileTime(fileHandle, NULL, &lastAccessTime, &lastModTime)) {
	TclWinConvertError(GetLastError());
	res = -1;
    }
    if (fileHandle != INVALID_HANDLE_VALUE) {
	CloseHandle(fileHandle);
    }
    return res;
}







|







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)) {
	Tcl_WinConvertError(GetLastError());
	res = -1;
    }
    if (fileHandle != INVALID_HANDLE_VALUE) {
	CloseHandle(fileHandle);
    }
    return res;
}

Changes to win/tclWinInit.c.

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.
 * 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"





|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
 * tclWinInit.c --
 *
 *	Contains the Windows-specific interpreter initialization functions.
 *
 * 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
 */

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
static const char *const processors[NUMPROCESSORS] = {
    "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "amd64", "ia32_on_win64"
};

/*
 * The default directory in which the init.tcl file is expected to be found.
 */

static TclInitProcessGlobalValueProc	InitializeDefaultLibraryDir;








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|


|







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 arrays contain the human readable strings for the
 * processor values.
 */

#define NUMPROCESSORS 15
static const char *const processors[NUMPROCESSORS] = {
    "intel", "mips", "alpha", "ppc", "shx", "arm", "ia64", "alpha64", "msil",
    "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
 */

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 --
 *







<


















<
<
<
<
<
<
<
<







80
81
82
83
84
85
86

87
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);


    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








}

/*
 *-------------------------------------------------------------------------
 *
 * 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
    size_t *lengthPtr,
    Tcl_Encoding *encodingPtr)
{
#define LIBRARY_SIZE	    64
    Tcl_Obj *pathPtr;
    char installLib[LIBRARY_SIZE];
    const char *bytes;
    size_t 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);

    /*
     * 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.
     */

    AppendEnvironment(pathPtr, installLib);

    /*
     * Look for the library in its default location.
     */







|









|





|







127
128
129
130
131
132
133
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;
    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.
     */

    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 original TCL_LIBRARY path.
     */

    AppendEnvironment(pathPtr, installLib);

    /*
     * Look for the library in its default location.
     */
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
 */

static void
AppendEnvironment(
    Tcl_Obj *pathPtr,
    const char *lib)
{
    int pathc;
    WCHAR wBuf[MAX_PATH];
    char buf[MAX_PATH * 3];
    Tcl_Obj *objPtr;
    Tcl_DString ds;
    const char **pathv;
    char *shortlib;








|







194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
 */

static void
AppendEnvironment(
    Tcl_Obj *pathPtr,
    const char *lib)
{
    Tcl_Size pathc;
    WCHAR wBuf[MAX_PATH];
    char buf[MAX_PATH * 3];
    Tcl_Obj *objPtr;
    Tcl_DString ds;
    const char **pathv;
    char *shortlib;

277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
	}
    }
    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.
     */

    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);
	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







|
|






|







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
	}
    }
    if (shortlib == lib) {
	Tcl_Panic("no '/' character found in lib");
    }

    /*
     * 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, 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
	     * 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);
	} else {
	    objPtr = Tcl_NewStringObj(buf, -1);
	}
	Tcl_ListObjAppendElement(NULL, pathPtr, objPtr);
	Tcl_Free((void *)pathv);
    }
}

/*







|

|







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 = Tcl_DStringToObj(&ds);
	} else {
	    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
    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);

    end = strrchr(name, '\\');
    *end = '\0';
    p = strrchr(name, '\\');
    if (p != NULL) {
	end = p;
    }
    *end = '\\';

    TclWinNoBackslash(name);
    sprintf(end + 1, "lib/tcl%s", TCL_VERSION);
    *lengthPtr = strlen(name);
    *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1);
    *encodingPtr = NULL;
    memcpy(*valuePtr, name, *lengthPtr + 1);
}

/*







|
|










|







288
289
290
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, 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);
    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
    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);

    end = strrchr(name, '\\');
    *end = '\0';
    p = strrchr(name, '\\');
    if (p != NULL) {
	end = p;
    }
    *end = '\\';

    TclWinNoBackslash(name);
    sprintf(end + 1, "../library");
    *lengthPtr = strlen(name);
    *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1);
    *encodingPtr = NULL;
    memcpy(*valuePtr, name, *lengthPtr + 1);
}

/*







|
|










|







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, 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);
    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
    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());
	Tcl_DStringSetLength(bufPtr, strlen(Tcl_DStringValue(bufPtr)));
    }
    return Tcl_DStringValue(bufPtr);
}

const char *
TclpGetUserName(







|







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);
	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
     * 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);



    wsprintfA(buffer, "%d.%d", 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);
	}
	ptr = Tcl_GetVar2(interp, "env", "HOMEPATH", TCL_GLOBAL_ONLY);
	if (ptr != NULL) {
	    Tcl_DStringAppend(&ds, ptr, -1);
	}
	if (Tcl_DStringLength(&ds) > 0) {
	    Tcl_SetVar2(interp, "env", "HOME", Tcl_DStringValue(&ds),
		    TCL_GLOBAL_ONLY);
	} else {






	    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.







>
>
>
|







<
<
<
<
<
<
<
<
<
<
<
<
<










|



|





>
>
>
>
>
>
|
>







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;
    }
    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);
    }














    /*
     * 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, TCL_INDEX_NONE);
	}
	ptr = Tcl_GetVar2(interp, "env", "HOMEPATH", TCL_GLOBAL_ONLY);
	if (ptr != NULL) {
	    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);
            }
	}
    }

    /*
     * 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
 * 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
 *	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
TclpFindVariable(
    const char *name,		/* Name of desired environment variable
				 * (UTF-8). */
    size_t *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;
    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];
	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);
	p1 = strchr(envUpper, '=');
	if (p1 == NULL) {
	    continue;
	}
	length = p1 - envUpper;
	Tcl_DStringSetLength(&envString, length+1);
	Tcl_UtfToUpper(envUpper);







|










<
<
<
|



|




|















|
<
<







|







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 -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.
 *
 *----------------------------------------------------------------------
 */




Tcl_Size
TclpFindVariable(
    const char *name,		/* Name of desired environment variable
				 * (UTF-8). */
    Tcl_Size *lengthPtr)		/* Used to return length of name (for
				 * successful searches) or number of non-NULL
				 * entries in environ (for unsuccessful
				 * searches). */
{
    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]; 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, 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
	    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 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








<
<
<
<
<
<
<
<
<












<
<









|
>







27
28
29
30
31
32
33









34
35
36
37
38
39
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










/*
 * 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 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

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
/*
 * 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.
 *
 * 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;

static Tcl_Mutex dllDirectoryNameMutex;


/*
 * Static functions defined within this file.
 */

static void *		FindSymbol(Tcl_Interp *interp,
			    Tcl_LoadHandle loadHandle, const char *symbol);







|














>

>







1
2
3
4
5
6
7
8
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 © 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);
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
         * 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);
	hInstance = LoadLibraryExW(nativeName, NULL,
		LOAD_WITH_ALTERED_SEARCH_PATH);
	Tcl_DStringFree(&ds);
    }

    if (hInstance == NULL) {
	DWORD lastError;
        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;


	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);
		goto notFoundMsg;
	    case ERROR_DLL_NOT_FOUND:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_NOT_FOUND", NULL);
	    notFoundMsg:
		Tcl_AppendToObj(errMsg, "this library or a dependent library"
			" could not be found in library path", -1);
		break;
	    case ERROR_PROC_NOT_FOUND:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "PROC_NOT_FOUND", 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);
		break;
	    case ERROR_INVALID_DLL:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "INVALID_DLL", NULL);
		Tcl_AppendToObj(errMsg, "this library or a dependent library"
			" is damaged", -1);
		break;
	    case ERROR_DLL_INIT_FAILED:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_INIT_FAILED", NULL);
		Tcl_AppendToObj(errMsg, "the library initialization"
			" routine failed", -1);
		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);
	    }
	    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->findSymbolProcPtr = &FindSymbol;
    handlePtr->unloadFileProcPtr = &UnloadFile;
    *loadHandle = handlePtr;
    *unloadProcPtr = &UnloadFile;
    return TCL_OK;
}








|















|

|

>














|


|


|


|


|


|

|


|

|


|
|


|
|











|







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
         * 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), TCL_INDEX_NONE, &ds);
	hInstance = LoadLibraryExW(nativeName, NULL,
		LOAD_WITH_ALTERED_SEARCH_PATH);
	Tcl_DStringFree(&ds);
    }

    if (hInstance == NULL) {
	DWORD lastError;
        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;
        }

	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", (char *)NULL);
		goto notFoundMsg;
	    case ERROR_DLL_NOT_FOUND:
		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", TCL_INDEX_NONE);
		break;
	    case ERROR_PROC_NOT_FOUND:
		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.", TCL_INDEX_NONE);
		break;
	    case ERROR_INVALID_DLL:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "INVALID_DLL", (char *)NULL);
		Tcl_AppendToObj(errMsg, "this library or a dependent library"
			" is damaged", TCL_INDEX_NONE);
		break;
	    case ERROR_DLL_INIT_FAILED:
		Tcl_SetErrorCode(interp, "WIN_LOAD", "DLL_INIT_FAILED", (char *)NULL);
		Tcl_AppendToObj(errMsg, "the library initialization"
			" routine failed", TCL_INDEX_NONE);
		break;
            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 = (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
    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);
	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);
    }
    return proc;
}

/*
 *----------------------------------------------------------------------
 *







|






|







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, 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, (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
				 * 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).







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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);
}





























/*
 *----------------------------------------------------------------------
 *
 * 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
	lastError = GetLastError();
	if (lastError != ERROR_ALREADY_EXISTS) {
	    break;
	}
	id *= 16777619;
    }

    TclWinConvertError(lastError);
    return TCL_ERROR;

    /*
     * Store our computed value in the global.
     */

  copyToGlobalBuffer:







|







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;
    }

    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
/*
 * 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.
 *
 * 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.
 */

#define INTERVAL_TIMER	1	/* Handle of interval timer. */

#define WM_WAKEUP	WM_USER	/* Message that is send by
				 * Tcl_AlertNotifier. */
/*







|








|







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 © 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 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
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);

/*
 *----------------------------------------------------------------------
 *
 * 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)
{
    if (tclNotifierHooks.initNotifierProc) {
	return tclNotifierHooks.initNotifierProc();
    } else {
	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

	TclpGlobalLock();
	if (!initialized) {
	    initialized = 1;
	    InitializeCriticalSection(&notifierMutex);
	}
	TclpGlobalUnlock();

	/*
	 * Register Notifier window class if this is the first thread to use
	 * this module.
	 */

	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;

	    if (!RegisterClassW(&clazz)) {

		Tcl_Panic("Unable to register TclNotifier window class");
	    }
	}
	notifierCount++;
	LeaveCriticalSection(&notifierMutex);

	tsdPtr->pending = 0;
	tsdPtr->timerActive = 0;

	InitializeCriticalSection(&tsdPtr->crit);

	tsdPtr->hwnd = NULL;
	tsdPtr->thread = GetCurrentThreadId();
	tsdPtr->event = CreateEventW(NULL, TRUE /* manual */,
		FALSE /* !signaled */, NULL);

	return tsdPtr;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FinalizeNotifier --
 *
 *	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. */
{
    if (tclNotifierHooks.finalizeNotifierProc) {
	tclNotifierHooks.finalizeNotifierProc(clientData);
	return;
    } else {
	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.
	 */

	if (tsdPtr == NULL) {
	    return;
	}

	DeleteCriticalSection(&tsdPtr->crit);
	CloseHandle(tsdPtr->event);

	/*
	 * Clean up the timer and messaging window for this thread.
	 */

	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.
	 */

	EnterCriticalSection(&notifierMutex);
	if (notifierCount) {
	    notifierCount--;
	    if (notifierCount == 0) {
		UnregisterClassW(className, (HINSTANCE)TclWinGetTclInstance());
	    }
	}
	LeaveCriticalSection(&notifierMutex);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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 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. */
{
    if (tclNotifierHooks.alertNotifierProc) {
	tclNotifierHooks.alertNotifierProc(clientData);
	return;
    } else {
	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.
	 */

	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);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_SetTimer --
 *
 *	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(
    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;

	/*
	 * 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 (!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, NULL);
	} else {
	    tsdPtr->timerActive = 0;
	    KillTimer(tsdPtr->hwnd, INTERVAL_TIMER);
	}
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_ServiceModeHook --
 *
 *	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(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{
    if (tclNotifierHooks.serviceModeHookProc) {
	tclNotifierHooks.serviceModeHookProc(mode);
	return;
    } else {
	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
	 * 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);

	    /*
	     * 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);
	}
    }

























}

/*
 *----------------------------------------------------------------------
 *
 * NotifierProc --
 *







|
|

















|
|

<
<
<
|

|
|
|
|
|
|

|
|
|
|

|
|
|

|
|
|
|
|
|
|
|
|
|

|
>
|
|
|
|
|

|
|

|

|
|
|
|

|
<





|














|
|

<
<
<
<
|

|
|
|
|
|
|
|
|
|
|

|
|
|

|
|

|
|
|

|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
<



|



















|
|

<
<
<
<
|

|
|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
<



|















|


<
<
<
<
|
|

|
|
|
|
|

|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
>
|
|
|
<
|
|
|
|
|
|
<



|














|



<
<
<
<
|

|
|
|
|
|
|
|
<
|

|
|
|
|

|
|
|
|
|
|

|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152




153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222




223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268




269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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);

/*
 *----------------------------------------------------------------------
 *
 * Tcl_InitNotifier --
 *
 *	Initializes the platform specific notifier state.
 *
 * Results:
 *	Returns a handle to the notifier state for this thread..
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void *
TclpInitNotifier(void)
{



    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

    TclpGlobalLock();
    if (!initialized) {
	initialized = 1;
	InitializeCriticalSection(&notifierMutex);
    }
    TclpGlobalUnlock();

    /*
     * Register Notifier window class if this is the first thread to use this
     * module.
     */

    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;

	if (!RegisterClassW(&clazz)) {
	    Tcl_Panic("Tcl_InitNotifier: %s",
		    "unable to register TclNotifier window class");
	}
    }
    notifierCount++;
    LeaveCriticalSection(&notifierMutex);

    tsdPtr->pending = 0;
    tsdPtr->timerActive = 0;

    InitializeCriticalSection(&tsdPtr->crit);

    tsdPtr->hwnd = NULL;
    tsdPtr->thread = GetCurrentThreadId();
    tsdPtr->event = CreateEventW(NULL, TRUE /* manual */,
	    FALSE /* !signaled */, NULL);

    return tsdPtr;

}

/*
 *----------------------------------------------------------------------
 *
 * 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
TclpFinalizeNotifier(
    void *clientData)	/* Pointer to notifier data. */
{




    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.
     */

    if (tsdPtr == NULL) {
	return;
    }

    DeleteCriticalSection(&tsdPtr->crit);
    CloseHandle(tsdPtr->event);

    /*
     * Clean up the timer and messaging window for this thread.
     */

    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.
     */

    EnterCriticalSection(&notifierMutex);
    if (notifierCount) {
	notifierCount--;
	if (notifierCount == 0) {
	    UnregisterClassW(className, (HINSTANCE) TclWinGetTclInstance());
	}
    }
    LeaveCriticalSection(&notifierMutex);
}


/*
 *----------------------------------------------------------------------
 *
 * 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
TclpAlertNotifier(
    void *clientData)	/* Pointer to thread data. */
{




    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.
     */

    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);
    }
}


/*
 *----------------------------------------------------------------------
 *
 * 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
TclpSetTimer(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
{




    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.
     */

    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.
	 */

	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);

    } else {
	tsdPtr->timerActive = 0;
	KillTimer(tsdPtr->hwnd, INTERVAL_TIMER);
    }
}


/*
 *----------------------------------------------------------------------
 *
 * 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
TclpServiceModeHook(
    int mode)			/* Either TCL_SERVICE_ALL, or
				 * TCL_SERVICE_NONE. */
{




    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 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);

	/*
	 * 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);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * 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
    Tcl_ServiceAll();
    return 0;
}

/*
 *----------------------------------------------------------------------
 *























 * Tcl_WaitForEvent --
 *
 *	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(
    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;

	/*
	 * Compute the timeout in milliseconds.
	 */

	if (timePtr) {
	    /*
	     * TIP #233 (Virtualized Time). Convert virtual domain delay to
	     * real-time.
	     */

	    Tcl_Time myTime;

	    myTime.sec  = timePtr->sec;
	    myTime.usec = timePtr->usec;

	    if (myTime.sec != 0 || myTime.usec != 0) {
		tclScaleTimeProcPtr(&myTime, tclTimeClientData);
	    }

	    timeout = myTime.sec * 1000 + 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.
	 */

	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:

	    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;
	    }
	}

	/*
	 * Check to see if there are any messages to process.
	 */

	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.
		 */

		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;
	}

      end:
	ResetEvent(tsdPtr->event);
	return status;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_Sleep --
 *







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
















|


<
<
<
|
|
|
|

|
|
|

|
|
|
|
|

|

|
|

|
|
|

|
|
|
|

|
|
|
|
|

|
|
|
|
|
|

<
>


|
|
|
|
|
|
|

|
|
|

|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
<







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;
}

/*
 *----------------------------------------------------------------------
 *
 * 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
TclpWaitForEvent(
    const Tcl_Time *timePtr)		/* Maximum block time, or NULL. */
{



    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
    MSG msg;
    DWORD timeout, result;
    int status;

    /*
     * Compute the timeout in milliseconds.
     */

    if (timePtr) {
	/*
	 * TIP #233 (Virtualized Time). Convert virtual domain delay to
	 * real-time.
	 */

	Tcl_Time myTime;

	myTime.sec  = timePtr->sec;
	myTime.usec = timePtr->usec;

	if (myTime.sec != 0 || myTime.usec != 0) {
	    TclScaleTime(&myTime);
	}

	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.
     */

    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.
	 */


	do {
	    result = MsgWaitForMultipleObjectsEx(1, &tsdPtr->event, timeout,
		    QS_ALLINPUT, MWMO_ALERTABLE);
	} while (result == WAIT_IO_COMPLETION);

	if (result == WAIT_FAILED) {
	    status = -1;
	    goto end;
	}
    }

    /*
     * Check to see if there are any messages to process.
     */

    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.
	     */

	    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;
    }

  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
	desired.usec -= 1000000;
    }

    /*
     * TIP #233: Scale delay from virtual to real-time.
     */

    tclScaleTimeProcPtr(&vdelay, tclTimeClientData);
    sleepTime = vdelay.sec * 1000 + 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;
    }
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







|
|













|
|










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.
     */

    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;

	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
 /*
 * tclWinPanic.c --
 *
 *	Contains the Windows-specific command-line panic proc.
 *
 * Copyright (c) 2013 by 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"





|







1
2
3
4
5
6
7
8
9
10
11
12
13
 /*
 * tclWinPanic.c --
 *
 *	Contains the Windows-specific command-line panic proc.
 *
 * 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"
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);
    } else {
	buf[0] = '\xEF'; buf[1] = '\xBB'; buf[2] = '\xBF'; /* UTF-8 bom */
	WriteFile(handle, buf, strlen(buf), &dummy, 0);
	WriteFile(handle, "\n", 1, &dummy, 0);
	FlushFileBuffers(handle);
    }
#   if defined(__GNUC__)
	__builtin_trap();
#   elif defined(_WIN64)
	__debugbreak();







|


|







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, (DWORD)wcslen(msgString), &dummy, 0);
    } else {
	buf[0] = '\xEF'; buf[1] = '\xBB'; buf[2] = '\xBF'; /* UTF-8 bom */
	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
/*
 * 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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"







|







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 © 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

/*
 * This list is used to map from pids to process handles.
 */

typedef struct ProcInfo {
    HANDLE hProcess;
    size_t dwProcessId;
    struct ProcInfo *nextPtr;
} ProcInfo;

static ProcInfo *procList;

/*
 * Bit masks used in the flags field of the PipeInfo structure below.







|







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;
    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
    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. */
    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. */







|







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. */
    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

/*
 * 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,
			    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,
			    Tcl_Interp *interp, int flags);
static int		PipeEventProc(Tcl_Event *evPtr, int flags);
static int		PipeGetHandleProc(ClientData instanceData,
			    int direction, ClientData *handlePtr);
static void		PipeInit(void);
static int		PipeInputProc(ClientData instanceData, char *buf,
			    int toRead, int *errorCode);
static int		PipeOutputProc(ClientData 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 DWORD WINAPI	PipeWriterThread(LPVOID arg);
static int		TempFileName(WCHAR name[MAX_PATH]);
static int		WaitForRead(PipeInfo *infoPtr, int blocking);
static void		PipeThreadActionProc(ClientData instanceData,
			    int action);

/*
 * This structure describes the channel type structure for command pipe based
 * I/O.
 */








|


|
|
|


|
|

|

|


|
|



|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

/*
 * 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, size_t argc,
			    const char **argv, Tcl_DString *linePtr);
static BOOL		HasConsole(void);
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(void *instanceData,
			    int direction, void **handlePtr);
static void		PipeInit(void);
static int		PipeInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		PipeOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);
static DWORD WINAPI	PipeReaderThread(LPVOID arg);
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(void *instanceData,
			    int action);

/*
 * This structure describes the channel type structure for command pipe based
 * I/O.
 */

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),
    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);








|







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(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
 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
PipeCheckProc(
    TCL_UNUSED(ClientData),
    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */
{
    PipeInfo *infoPtr;
    PipeEvent *evPtr;
    int needEvent;
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);








|







359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
PipeCheckProc(
    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
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) {
	return TclWinMakeFile(handle);
    } else {
	return (TclFile) NULL;
    }
}

/*







|







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,
	    (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
    Tcl_DString ds;
    const WCHAR *nativePath;

    /*
     * Map the access bits to the NT access mode.
     */

    switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) {
    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);
	return NULL;
    }

    /*
     * Map the creation flags to the NT create mode.
     */








|










|







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_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:
	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
	break;
    default:
	createMode = OPEN_EXISTING;
	break;
    }

    Tcl_DStringInit(&ds);
    nativePath = Tcl_UtfToWCharDString(path, -1, &ds);

    /*
     * If the file is not being created, use the existing file attributes.
     */

    flags = 0;
    if (!(mode & O_CREAT)) {







|







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, 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
    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);
	return NULL;
    }

    /*
     * Seek to the end of file if we are writing.
     */








|







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;
	}
	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
 */

TclFile
TclpCreateTempFile(
    const char *contents)	/* String to write into temp file, or NULL. */
{
    WCHAR name[MAX_PATH];
    const char *native;
    Tcl_DString dstring;
    HANDLE handle;

    if (TempFileName(name) == 0) {
	return NULL;
    }








|







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 = 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
	const char *p;
	int toCopy;

	/*
	 * Convert the contents from UTF to native encoding
	 */

	native = Tcl_UtfToExternalDString(NULL, contents, -1, &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)) {







|
>
>
>







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
	 */

	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
     * Free the native representation of the contents if necessary.
     */

    if (contents != NULL) {
	Tcl_DStringFree(&dstring);
    }


    TclWinConvertError(GetLastError());

    CloseHandle(handle);
    DeleteFileW(name);
    return NULL;
}

/*
 *----------------------------------------------------------------------







>
|
>







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) {
	Tcl_WinConvertError(GetLastError());
    }
    CloseHandle(handle);
    DeleteFileW(name);
    return NULL;
}

/*
 *----------------------------------------------------------------------
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794

    if (CreatePipe(&readHandle, &writeHandle, NULL, 0) != 0) {
	*readPipe = TclWinMakeFile(readHandle);
	*writePipe = TclWinMakeFile(writeHandle);
	return 1;
    }

    TclWinConvertError(GetLastError());
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpCloseFile --







|







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;
    }

    Tcl_WinConvertError(GetLastError());
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpCloseFile --
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835

	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_Free(filePtr);
		return -1;
	    }
	}
	break;

    default:







|







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) {
		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
 *
 * Side effects:
 *	None.
 *
 *--------------------------------------------------------------------------
 */

size_t
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) {
	    Tcl_MutexUnlock(&pipeMutex);
	    return infoPtr->dwProcessId;
	}
    }
    Tcl_MutexUnlock(&pipeMutex);
    return TCL_INDEX_NONE;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpCreateProcess --
 *







|









|





|







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.
 *
 *--------------------------------------------------------------------------
 */

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 == (Tcl_Size)pid) {
	    Tcl_MutexUnlock(&pipeMutex);
	    return infoPtr->dwProcessId;
	}
    }
    Tcl_MutexUnlock(&pipeMutex);
    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

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. */
    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
				 * 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
				 * 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;







|











|




|







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. */
    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 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 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
	    CloseHandle(h);
	}
    } else {
	DuplicateHandle(hProcess, inputHandle, hProcess, &startInfo.hStdInput,
		0, TRUE, DUPLICATE_SAME_ACCESS);
    }
    if (startInfo.hStdInput == INVALID_HANDLE_VALUE) {
	TclWinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't duplicate input handle: %s",
		Tcl_PosixError(interp)));
	goto end;
    }

    if (outputHandle == INVALID_HANDLE_VALUE) {







|







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) {
	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
	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_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_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;
    } 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.







|



















|




















|







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) {
	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) {
	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;
    } 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
     */

    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_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.







|







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) {
	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
     * 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;
    if (*pidPtr != 0) {
	TclWinAddProcess(procInfo.hProcess, procInfo.dwProcessId);
    }
    result = TCL_OK;

  end:
    Tcl_DStringFree(&cmdLine);







|







1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
     * CreateProcessW() and CloseHandle(), the problem does not occur." PSS ID
     * Number: Q124121
     */

    WaitForInputIdle(procInfo.hProcess, 5000);
    CloseHandle(procInfo.hThread);

    *pidPtr = (Tcl_Pid)INT2PTR(procInfo.dwProcessId);
    if (*pidPtr != 0) {
	TclWinAddProcess(procInfo.hProcess, procInfo.dwProcessId);
    }
    result = TCL_OK;

  end:
    Tcl_DStringFree(&cmdLine);
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
     * 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);
    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_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));
	Tcl_DStringFree(&ds);

	ext = strrchr(fullName, '.');
	if ((ext != NULL) &&
            (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);
	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.







|




|




















|




|












|







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
     * 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, 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], 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, TCL_INDEX_NONE, &ds));
	Tcl_DStringFree(&ds);

	ext = strrchr(fullName, '.');
	if ((ext != NULL) &&
		(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);
	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

	/*
	 * 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);
	CloseHandle(hFile);

	if ((buf[0] == 'N') && (buf[1] == 'E')) {
	    applType = APPL_WIN3X;
	} else if ((buf[0] == 'P') && (buf[1] == 'E')) {
	    applType = APPL_WIN32;
	} else {







|







1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379

	/*
	 * 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);
	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
	    applType = APPL_DOS;
	}
	break;
    }
    Tcl_DStringFree(&nameBuf);

    if (applType == APPL_NONE) {
	TclWinConvertError(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));
	Tcl_DStringFree(&ds);
    }
    return applType;
}

/*
 *----------------------------------------------------------------------







|















|







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
	    applType = APPL_DOS;
	}
	break;
    }
    Tcl_DStringFree(&nameBuf);

    if (applType == APPL_NONE) {
	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, TCL_INDEX_NONE, &ds));
	Tcl_DStringFree(&ds);
    }
    return applType;
}

/*
 *----------------------------------------------------------------------
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
    return special;
}

static void
BuildCommandLine(
    const char *executable,	/* Full path of executable (including
				 * extension). Replacement for argv[0]. */
    int 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;

    Tcl_DString ds;


    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). */






    /*
     * 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};







|





|
>

>
>






>
>
>
>
>
>







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
    return special;
}

static void
BuildCommandLine(
    const char *executable,	/* Full path of executable (including
				 * extension). Replacement for argv[0]. */
    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;
    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
	    TclDStringAppendLiteral(&ds, "\"");
	}
	if (!(quote & CL_ESCAPE)) {
	    /*
	     * Nothing to escape.
	     */

	    Tcl_DStringAppend(&ds, arg, -1);
	} else {
	    start = arg;
	    for (special = arg; *special != '\0'; ) {
		/*
		 * Position of `\` is important before quote or at end (equal
		 * `\"` because quoted).
		 */







|







1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
	    TclDStringAppendLiteral(&ds, "\"");
	}
	if (!(quote & CL_ESCAPE)) {
	    /*
	     * Nothing to escape.
	     */

	    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
		    /*
		     * Start to current or first backslash
		     */

		    start = !bspos ? special : bspos;
		    continue;
		}

		/*
		 * 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;
		}


		/*
		 * Other not special (and not meta) character
		 */

		bspos = NULL;		/* reset last backslash position (not
					 * interesting) */







|
















>







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
		    /*
		     * 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

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. */
    Tcl_Pid *pidPtr)		/* An array of process identifiers. */
{
    char channelName[16 + TCL_INTEGER_SPACE];
    PipeInfo *infoPtr = (PipeInfo *)Tcl_Alloc(sizeof(PipeInfo));

    PipeInit();








|







1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784

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. */
    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();

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
    /*
     * 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);
    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 --







|



<
<
<
<
<
<

<







1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843






1844

1845
1846
1847
1848
1849
1850
1851
    /*
     * 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).
     */

    TclWinGenerateChannelName(channelName, "file", infoPtr);
    infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,
	    infoPtr, infoPtr->validMask);







    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");

    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
    SECURITY_ATTRIBUTES sec;

    sec.nLength = sizeof(SECURITY_ATTRIBUTES);
    sec.lpSecurityDescriptor = NULL;
    sec.bInheritHandle = FALSE;

    if (!CreatePipe(&readHandle, &writeHandle, &sec, 0)) {
	TclWinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"pipe creation failed: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }

    *rchan = Tcl_MakeFileChannel((ClientData) readHandle, TCL_READABLE);
    Tcl_RegisterChannel(interp, *rchan);

    *wchan = Tcl_MakeFileChannel((ClientData) writeHandle, TCL_WRITABLE);
    Tcl_RegisterChannel(interp, *wchan);

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|





|


|







1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
    SECURITY_ATTRIBUTES sec;

    sec.nLength = sizeof(SECURITY_ATTRIBUTES);
    sec.lpSecurityDescriptor = NULL;
    sec.bInheritHandle = FALSE;

    if (!CreatePipe(&readHandle, &writeHandle, &sec, 0)) {
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"pipe creation failed: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }

    *rchan = Tcl_MakeFileChannel((void *)readHandle, TCL_READABLE);
    Tcl_RegisterChannel(interp, *rchan);

    *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
TclGetAndDetachPids(
    Tcl_Interp *interp,
    Tcl_Channel chan)
{
    PipeInfo *pipePtr;
    const Tcl_ChannelType *chanTypePtr;
    Tcl_Obj *pidsObj;
    int i;

    /*
     * Punt if the channel is not a command channel.
     */

    chanTypePtr = Tcl_GetChannelType(chan);
    if (chanTypePtr != &pipeChannelType) {







|







1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
TclGetAndDetachPids(
    Tcl_Interp *interp,
    Tcl_Channel chan)
{
    PipeInfo *pipePtr;
    const Tcl_ChannelType *chanTypePtr;
    Tcl_Obj *pidsObj;
    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
 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
PipeBlockModeProc(
    ClientData 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,







|







1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
PipeBlockModeProc(
    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
 *	Closes the physical channel.
 *
 *----------------------------------------------------------------------
 */

static int
PipeClose2Proc(
    ClientData 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;







|







1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
 *	Closes the physical channel.
 *
 *----------------------------------------------------------------------
 */

static int
PipeClose2Proc(
    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
	 * 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,
		    TCL_READABLE);
	    Tcl_Free(filePtr);

	} else {
	    errChan = NULL;
	}

	result = TclCleanupChildren(interp, pipePtr->numPids,
		pipePtr->pidPtr, errChan);
    }







|


>







2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
	 * 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((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
 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
PipeInputProc(
    ClientData 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;







|







2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
PipeInputProc(
    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
	/*
	 * Ignore errors if we have data to return.
	 */

	return bytesRead;
    }

    TclWinConvertError(GetLastError());
    if (errno == EPIPE) {
	infoPtr->readFlags |= PIPE_EOF;
	return 0;
    }
    *errorCode = errno;
    return -1;
}







|







2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
	/*
	 * Ignore errors if we have data to return.
	 */

	return bytesRead;
    }

    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
 *	Writes output on the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
PipeOutputProc(
    ClientData 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;







|







2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
 *	Writes output on the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
PipeOutputProc(
    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
    }

    /*
     * Check for a background error on the last write.
     */

    if (infoPtr->writeError) {
	TclWinConvertError(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







|







2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
    }

    /*
     * Check for a background error on the last write.
     */

    if (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
	/*
	 * 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());
	    goto error;
	}
    }
    return bytesWritten;

  error:
    *errorCode = errno;







|







2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
	/*
	 * 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) {
	    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
PipeWatchProc(
    ClientData 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;







|







2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
PipeWatchProc(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PipeGetHandleProc(
    ClientData instanceData,	/* The pipe state. */
    int direction,		/* TCL_READABLE or TCL_WRITABLE */
    ClientData *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;
	return TCL_OK;
    }
    if (direction == TCL_WRITABLE && infoPtr->writeFile) {
	filePtr = (WinFile*) infoPtr->writeFile;
	*handlePtr = (ClientData) filePtr->handle;
	return TCL_OK;
    }
    return TCL_ERROR;
}

/*
 *----------------------------------------------------------------------







|

|






|




|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
PipeGetHandleProc(
    void *instanceData,	/* The pipe state. */
    int direction,		/* TCL_READABLE or TCL_WRITABLE */
    void **handlePtr)	/* Where to store the handle.  */
{
    PipeInfo *infoPtr = (PipeInfo *) instanceData;
    WinFile *filePtr;

    if (direction == TCL_READABLE && infoPtr->readFile) {
	filePtr = (WinFile*) infoPtr->readFile;
	*handlePtr = (void *)filePtr->handle;
	return TCL_OK;
    }
    if (direction == TCL_WRITABLE && infoPtr->writeFile) {
	filePtr = (WinFile*) infoPtr->writeFile;
	*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
     * 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) {
	    *prevPtrPtr = infoPtr->nextPtr;
	    break;
	}
    }
    Tcl_MutexUnlock(&pipeMutex);

    /*







|







2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
     * 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 == (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
	    *statPtr = exitCode;
	    break;
	}
	result = pid;
    } else {
	errno = ECHILD;
	*statPtr = 0xC0000000 | ECHILD;
	result = (Tcl_Pid) -1;
    }

    /*
     * Officially close the process handle.
     */

    CloseHandle(infoPtr->hProcess);







|







2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
	    *statPtr = exitCode;
	    break;
	}
	result = pid;
    } else {
	errno = ECHILD;
	*statPtr = 0xC0000000 | ECHILD;
	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
 *
 *----------------------------------------------------------------------
 */

void
TclWinAddProcess(
    void *hProcess,		/* Handle to process */
    size_t id)		/* Global process identifier */
{
    ProcInfo *procPtr = (ProcInfo*)Tcl_Alloc(sizeof(ProcInfo));

    PipeInit();

    procPtr->hProcess = hProcess;
    procPtr->dwProcessId = id;
    Tcl_MutexLock(&pipeMutex);
    procPtr->nextPtr = procList;







|

|







2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
 *
 *----------------------------------------------------------------------
 */

void
TclWinAddProcess(
    void *hProcess,		/* Handle to process */
    Tcl_Size id)		/* Global process identifier */
{
    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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PidObjCmd(
    TCL_UNUSED(ClientData),
    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;
    Tcl_Obj *resultPtr;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
	return TCL_ERROR;
    }
    if (objc == 1) {
	Tcl_SetObjResult(interp, Tcl_NewWideIntObj((unsigned) 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)
			    TclpGetPid(pipePtr->pidPtr[i])));
	}
	Tcl_SetObjResult(interp, resultPtr);
    }
    return TCL_OK;
}








|







|







|















|







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
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tcl_PidObjCmd(
    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;
    size_t i;
    Tcl_Obj *resultPtr;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?channelId?");
	return TCL_ERROR;
    }
    if (objc == 1) {
	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(
			    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
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;

    while (1) {
	/*
	 * Synchronize with the reader thread.
	 */

	/* avoid blocking if pipe-thread exited */







|







2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
static int
WaitForRead(
    PipeInfo *infoPtr,		/* Pipe state. */
    int blocking)		/* Indicates whether call should be blocking
				 * or not. */
{
    DWORD timeout, count;
    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

	/*
	 * 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());

	    /*
	     * Check to see if the peek failed because of EOF.
	     */

	    if (errno == EPIPE) {
		infoPtr->readFlags |= PIPE_EOF;







|







2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869

	/*
	 * 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) {
	    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
 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
PipeThreadActionProc(
    ClientData 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
     * this structure.
     */

    Tcl_MutexLock(&pipeMutex);
    if (action == TCL_CHANNEL_THREAD_INSERT) {
	/*
	 * We can't copy the thread information from the channel when the







|







|







3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
PipeThreadActionProc(
    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 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
    TCL_UNUSED(Tcl_Obj *) /*extensionObj*/,
    Tcl_Obj *resultingNameObj)
{
    WCHAR name[MAX_PATH];
    char *namePtr;
    HANDLE handle;
    DWORD flags = FILE_ATTRIBUTE_TEMPORARY;
    size_t length;
    int counter, counter2;
    Tcl_DString buf;

    if (!resultingNameObj) {
	flags |= FILE_FLAG_DELETE_ON_CLOSE;
    }








|







3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
    TCL_UNUSED(Tcl_Obj *) /*extensionObj*/,
    Tcl_Obj *resultingNameObj)
{
    WCHAR name[MAX_PATH];
    char *namePtr;
    HANDLE handle;
    DWORD flags = FILE_ATTRIBUTE_TEMPORARY;
    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
    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);
	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);








|







3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
    counter = TclpGetClicks() % 65533;
    counter2 = 1024;			/* Only try this many times! Prevents
					 * an infinite loop. */

    do {
	char number[TCL_INTEGER_SPACE + 4];

	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
    if (resultingNameObj) {
	Tcl_Obj *tmpObj = TclpNativeToNormalized(name);

	Tcl_AppendObjToObj(resultingNameObj, tmpObj);
	TclDecrRefCount(tmpObj);
    }

    return Tcl_MakeFileChannel((ClientData) handle,
	    TCL_READABLE|TCL_WRITABLE);

  gotError:
    TclWinConvertError(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,
    HANDLE wakeEvent)
{
    TclPipeThreadInfo *pipeTI;
#ifndef _PTI_USE_CKALLOC
    pipeTI = (TclPipeThreadInfo *)malloc(sizeof(TclPipeThreadInfo));
#else
    pipeTI = (TclPipeThreadInfo *)Tcl_Alloc(sizeof(TclPipeThreadInfo));







|



|



















|







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
    if (resultingNameObj) {
	Tcl_Obj *tmpObj = TclpNativeToNormalized(name);

	Tcl_AppendObjToObj(resultingNameObj, tmpObj);
	TclDecrRefCount(tmpObj);
    }

    return Tcl_MakeFileChannel((void *)handle,
	    TCL_READABLE|TCL_WRITABLE);

  gotError:
    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,
    void *clientData,
    HANDLE wakeEvent)
{
    TclPipeThreadInfo *pipeTI;
#ifndef _PTI_USE_CKALLOC
    pipeTI = (TclPipeThreadInfo *)malloc(sizeof(TclPipeThreadInfo));
#else
    pipeTI = (TclPipeThreadInfo *)Tcl_Alloc(sizeof(TclPipeThreadInfo));
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587

	    SetEvent(evControl);

	    /*
	     * Cancel all sync-IO of this thread (may be blocked there).
	     */

	    if (tclWinProcs.cancelSynchronousIo) {
		tclWinProcs.cancelSynchronousIo(hThread);
	    }

	    /*
	     * Wait at most 20 milliseconds for the reader thread to close
	     * (regarding TIP#398-fast-exit).
	     */

	    /*







<
|
<







3580
3581
3582
3583
3584
3585
3586

3587

3588
3589
3590
3591
3592
3593
3594

	    SetEvent(evControl);

	    /*
	     * Cancel all sync-IO of this thread (may be blocked there).
	     */


	    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
	&& !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
 */

#ifndef WINVER
#   define WINVER 0x0501
#endif
#ifndef _WIN32_WINNT
#   define _WIN32_WINNT 0x0501
#endif

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN

/* Compatibility to older visual studio / windows platform SDK */







|



|


|







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 = 0x0601 means Windows 7 and above
 */

#ifndef WINVER
#   define WINVER 0x0601
#endif
#ifndef _WIN32_WINNT
#   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
#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>
#   endif /* __BORLANDC__ */
#endif /* __MWERKS__ */

/*
 * The following defines redefine the Windows Socket errors as
 * BSD errors so Tcl_PosixError can do the right thing.
 */








<
<
<
<
<
<













<
<
<
|
<







88
89
90
91
92
93
94






95
96
97
98
99
100
101
102
103
104
105
106
107



108

109
110
111
112
113
114
115
#include <malloc.h>
#include <process.h>
#include <signal.h>
#ifdef HAVE_INTTYPES_H
#   include <inttypes.h>
#endif
#include <limits.h>






#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>



#include <sys/utime.h>

#endif /* __MWERKS__ */

/*
 * The following defines redefine the Windows Socket errors as
 * BSD errors so Tcl_PosixError can do the right thing.
 */

351
352
353
354
355
356
357



358
359
360
361
362
363
364
#endif
#ifndef W_OK
#    define W_OK 02
#endif
#ifndef R_OK
#    define R_OK 04
#endif




/*
 * Define macros to query file type bits, if they're not already
 * defined.
 */

#ifndef S_IFLNK







>
>
>







341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
#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
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
 * 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)
#	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: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)
#   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.







<
<
<


|




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>





<
|
|
<







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
 * 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



#   define exception _exception
#   undef EDEADLOCK
#   if defined(_MSC_VER)
#	define timezone _timezone
#   endif
#endif /* _MSC_VER || __MSVCRT__ */






















#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

#   pragma warning(disable:4267)
#   pragma warning(disable:4996)

#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

/*
 * The following defines wrap the system memory allocation routines for
 * use by tclAlloc.c.
 */

#define TclpSysAlloc(size)		((void*)HeapAlloc(GetProcessHeap(), \
					    (DWORD)0, (DWORD)size))
#define TclpSysFree(ptr)		(HeapFree(GetProcessHeap(), \
					    (DWORD)0, (HGLOBAL)ptr))
#define TclpSysRealloc(ptr, size)	((void*)HeapReAlloc(GetProcessHeap(), \
					    (DWORD)0, (LPVOID)ptr, (DWORD)size))

/* This type is not defined in the Windows headers */
#define socklen_t       int


/*
 * The following macros have trivial definitions, allowing generic code to







|

|

|







511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529

/*
 * The following defines wrap the system memory allocation routines for
 * use by tclAlloc.c.
 */

#define TclpSysAlloc(size)		((void*)HeapAlloc(GetProcessHeap(), \
					    0, size))
#define TclpSysFree(ptr)		(HeapFree(GetProcessHeap(), \
					    0, (HGLOBAL)ptr))
#define TclpSysRealloc(ptr, size)	((void*)HeapReAlloc(GetProcessHeap(), \
					    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

Changes to win/tclWinReg.c.

82
83
84
85
86
87
88
















89
90
91
92
93
94
95
96
97
98
99
100
101
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;

















/*
 * Declarations for functions defined in this file.
 */

static void		AppendSystemError(Tcl_Interp *interp, DWORD error);
static int		BroadcastValue(Tcl_Interp *interp, int 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);







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|







82
83
84
85
86
87
88
89
90
91
92
93
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 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, 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
			    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_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);





#ifdef __cplusplus
}
#endif

/*
 *----------------------------------------------------------------------
 *







|





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<





>
>
>
>
>







130
131
132
133
134
135
136
137
138
139
140
141
142





























143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
			    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, 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);






























#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

int
Registry_Init(
    Tcl_Interp *interp)
{
    Tcl_Command cmd;

    if (Tcl_InitStubs(interp, "8.5", 0) == NULL) {
	return TCL_ERROR;
    }

    cmd = Tcl_CreateObjCommand(interp, "registry", RegistryObjCmd,
	    interp, DeleteCmd);
    Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, cmd);
    return Tcl_PkgProvideEx(interp, "registry", "1.3.5", NULL);
}









/*
 *----------------------------------------------------------------------
 *
 * Registry_Unload --
 *
 *	This function removes the registry command.







|



|


|

>
>
>
>
>
>
>
>







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202

int
Registry_Init(
    Tcl_Interp *interp)
{
    Tcl_Command cmd;

    if (Tcl_InitStubs(interp, "8.5-", 0) == NULL) {
	return TCL_ERROR;
    }

    cmd = Tcl_CreateObjCommand2(interp, "registry", RegistryObjCmd,
	    interp, DeleteCmd);
    Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, cmd);
    return Tcl_PkgProvideEx(interp, "registry", "1.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
    cmd = (Tcl_Command)Tcl_GetAssocData(interp, REGISTRY_ASSOC_KEY, NULL);
    if (cmd != NULL) {
	Tcl_DeleteCommandFromToken(interp, cmd);
    }

    return TCL_OK;
}










/*
 *----------------------------------------------------------------------
 *
 * DeleteCmd --
 *
 *	Cleanup the interp command token so that unloading doesn't try to







>
>
>
>
>
>
>
>
>







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    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
 *----------------------------------------------------------------------
 */

static int
RegistryObjCmd(
    void *dummy,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    int n = 1;
    int index, argc;
    REGSAM mode = 0;
    const char *errString = NULL;

    static const char *const subcommands[] = {
	"broadcast", "delete", "get", "keys", "set", "type", "values", NULL
    };
    enum SubCmdIdx {







|


|
|







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
 *----------------------------------------------------------------------
 */

static int
RegistryObjCmd(
    void *dummy,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    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 {
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
{
    char *tail, *buffer, *hostName, *keyName;
    const WCHAR *nativeTail;
    HKEY rootKey, subkey;
    DWORD result;
    Tcl_DString buf;
    REGSAM saveMode = mode;


    /*
     * Find the parent of the key being deleted and open it.
     */

    keyName = Tcl_GetString(keyNameObj);
    buffer = (char *)Tcl_Alloc(keyNameObj->length + 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_Free(buffer);
	return TCL_ERROR;
    }

    tail = strrchr(keyName, '\\');
    if (tail) {
	*tail++ = '\0';







>





|
|











|







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
{
    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_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", (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
    Tcl_Obj *valueNameObj,	/* Name of value to delete. */
    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    char *valueName;
    DWORD result;
    Tcl_DString ds;


    /*
     * 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);
    Tcl_DStringInit(&ds);
    Tcl_UtfToWCharDString(valueName, valueNameObj->length, &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);







>










|

|







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_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_GetStringFromObj(valueNameObj, &len);
    Tcl_DStringInit(&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
    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    DWORD result, type;
    Tcl_DString ds;
    const char *valueName;
    const WCHAR *nativeValue;


    /*
     * 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);
    Tcl_DStringInit(&ds);
    nativeValue = Tcl_UtfToWCharDString(valueName, valueNameObj->length, &ds);
    result = RegQueryValueExW(key, nativeValue, NULL, &type,
	    NULL, NULL);
    Tcl_DStringFree(&ds);
    RegCloseKey(key);

    if (result != ERROR_SUCCESS) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(







>














|

|







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
    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_GetStringFromObj(valueNameObj, &len);
    Tcl_DStringInit(&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
    REGSAM mode)		/* Mode flags to pass. */
{
    HKEY key;
    const char *valueName;
    const WCHAR *nativeValue;
    DWORD result, length, type;
    Tcl_DString data, buf;


    /*
     * 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.
     * 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);
    Tcl_DStringInit(&buf);
    nativeValue = Tcl_UtfToWCharDString(valueName, valueNameObj->length, &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));
	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(







>
















|







|

|











|







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
    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 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_GetStringFromObj(valueNameObj, &len);
    Tcl_DStringInit(&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, 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

	    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 */}
	    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));
    }
    Tcl_DStringFree(&data);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * GetValueNames --
 *
 *	This function enumerates the values of the a 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.
 *







|















|










|







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

	    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 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), length));
    }
    Tcl_DStringFree(&data);
    return result;
}

/*
 *----------------------------------------------------------------------
 *
 * GetValueNames --
 *
 *	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
    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)));
    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) {







|


















<







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
    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, 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
    REGSAM mode,		/* Access mode. */
    int flags,			/* 0 or REG_CREATE. */
    HKEY *keyPtr)		/* Returned HKEY. */
{
    char *keyName, *buffer, *hostName;
    HKEY rootKey;
    DWORD result;


    keyName = Tcl_GetString(keyNameObj);
    buffer = (char *)Tcl_Alloc(keyNameObj->length + 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,







>

|
|







983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
    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_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
}

/*
 *----------------------------------------------------------------------
 *
 * OpenSubKey --
 *
 *	This function opens a given subkey of a 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:







|







1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
}

/*
 *----------------------------------------------------------------------
 *
 * OpenSubKey --
 *
 *	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
}

/*
 *----------------------------------------------------------------------
 *
 * ParseKeyName --
 *
 *	This function 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:







|







1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
}

/*
 *----------------------------------------------------------------------
 *
 * ParseKeyName --
 *
 *	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
	}
    } 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);
	return TCL_ERROR;
    }

    /*
     * Split the root into root and subkey portions.
     */








|







1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
	}
    } 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", (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
    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)));

    mode = saveMode;
    while (result == ERROR_SUCCESS) {
	/*
	 * Always get index 0 because key deletion changes ordering.
	 */








|







1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
    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, 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
    REGSAM mode)		/* Mode flags to pass. */
{
    int type;
    DWORD result;
    HKEY key;
    const char *valueName;
    Tcl_DString nameBuf;


    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) {
	return TCL_ERROR;
    }

    valueName = Tcl_GetString(valueNameObj);
    Tcl_DStringInit(&nameBuf);
    valueName = (char *) Tcl_UtfToWCharDString(valueName, valueNameObj->length, &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_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]);

	    Tcl_DStringAppend(&data, bytes, objv[i]->length);

	    /*
	     * 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);

	Tcl_DStringInit(&buf);
	data = (char *) Tcl_UtfToWCharDString(data, dataObj->length, &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;

	/*
	 * Store binary data in the registry.
	 */

	data = (BYTE *) getByteArrayFromObj(dataObj, &bytelength);
	result = RegSetValueExW(key, (WCHAR *) valueName, 0,
		(DWORD) type, data, (DWORD) bytelength);
    }

    Tcl_DStringFree(&nameBuf);
    RegCloseKey(key);








>















|

|















|
















|

|


















|


|












|





|







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
    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) {
	return TCL_ERROR;
    }

    valueName = Tcl_GetStringFromObj(valueNameObj, &len);
    Tcl_DStringInit(&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;
	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_GetStringFromObj(objv[i], &len);

	    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_GetStringFromObj(dataObj, &len);

	Tcl_DStringInit(&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;
	Tcl_Size bytelength;

	/*
	 * Store binary data in the registry.
	 */

	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
 *
 *----------------------------------------------------------------------
 */

static int
BroadcastValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    LRESULT result;
    DWORD_PTR sendResult;
    int timeout = 3000;
    size_t len;
    const char *str;
    Tcl_Obj *objPtr;
    WCHAR *wstr;
    Tcl_DString ds;

    if (objc == 3) {
	str = Tcl_GetString(objv[1]);
	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]);
    Tcl_DStringInit(&ds);
    wstr = Tcl_UtfToWCharDString(str, objv[0]->length, &ds);
    if (Tcl_DStringLength(&ds) == 0) {
	wstr = NULL;
    }

    /*
     * Use the ignore the result.
     */







|





|






|
<








|

|







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
 *
 *----------------------------------------------------------------------
 */

static int
BroadcastValue(
    Tcl_Interp *interp,		/* Current interpreter. */
    Tcl_Size objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument values. */
{
    LRESULT result;
    DWORD_PTR sendResult;
    int timeout = 3000;
    Tcl_Size len;
    const char *str;
    Tcl_Obj *objPtr;
    WCHAR *wstr;
    Tcl_DString ds;

    if (objc == 3) {
	str = Tcl_GetStringFromObj(objv[1], &len);

	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_GetStringFromObj(objv[0], &len);
    Tcl_DStringInit(&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
}

/*
 *----------------------------------------------------------------------
 *
 * AppendSystemError --
 *
 *	This routine formats a Windows system error message and places it into
 *	the interpreter result.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.







|







1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
}

/*
 *----------------------------------------------------------------------
 *
 * AppendSystemError --
 *
 *	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
	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);
	msg = msgBuf;
    } else {
	char *msgPtr;

	Tcl_DStringInit(&ds);
	Tcl_WCharToUtfDString(tMsgPtr, wcslen(tMsgPtr), &ds);
	LocalFree(tMsgPtr);







|







1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
	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) {
	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
	if (msgPtr[length-1] == '\r') {
	    --length;
	}
	msgPtr[length] = 0;
	msg = msgPtr;
    }

    sprintf(id, "%ld", error);
    Tcl_SetErrorCode(interp, "WINDOWS", id, msg, 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
 *	returns the appropriately swapped value.
 *
 * Results:
 *	Returns a converted DWORD.
 *
 * Side effects:
 *	None.







|
|













|







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
	if (msgPtr[length-1] == '\r') {
	    --length;
	}
	msgPtr[length] = 0;
	msg = msgPtr;
    }

    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 --
 *
 *	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
/*
 * tclWinSerial.c --
 *
 *	This file implements the Windows-specific serial port functions, and
 *	the "serial" channel driver.
 *
 * Copyright (c) 1999 by 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 [email protected]
 */







|







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 © 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 [email protected]
 */

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
				 * 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,







|







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 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
    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,
			    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 ThreadSpecificData *SerialInit(void);
static int		SerialInputProc(ClientData instanceData, char *buf,
			    int toRead, int *errorCode);
static int		SerialOutputProc(ClientData 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,
			    Tcl_Interp *interp, const char *optionName,
			    Tcl_DString *dsPtr);
static int		SerialSetOptionProc(ClientData instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *value);
static DWORD WINAPI	SerialWriterThread(LPVOID arg);
static void		SerialThreadActionProc(ClientData 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);








|
|
|


|
|
|

|

|

|
|
|
|


|



|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
    0,			/* WriteTotalTimeoutConstant */
};

/*
 * Declarations for functions used only in this file.
 */

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(void *clientData);
static int		SerialGetHandleProc(void *instanceData,
			    int direction, void **handlePtr);
static ThreadSpecificData *SerialInit(void);
static int		SerialInputProc(void *instanceData, char *buf,
			    int toRead, int *errorCode);
static int		SerialOutputProc(void *instanceData,
			    const char *buf, int toWrite, int *errorCode);
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(void *instanceData,
			    Tcl_Interp *interp, const char *optionName,
			    const char *value);
static DWORD WINAPI	SerialWriterThread(LPVOID arg);
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);

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))
{
    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







|







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(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
 *	Resets the process list.
 *
 *----------------------------------------------------------------------
 */

static void
ProcExitHandler(
    TCL_UNUSED(ClientData))
{
    Tcl_MutexLock(&serialMutex);
    initialized = 0;
    Tcl_MutexUnlock(&serialMutex);
}

/*
 *----------------------------------------------------------------------
 *
 * SerialBlockTime --
 *
 *	Wrapper to set Tcl's block time in msec
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Updates the maximum blocking time.
 *







|











|







319
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(void *))
{
    Tcl_MutexLock(&serialMutex);
    initialized = 0;
    Tcl_MutexUnlock(&serialMutex);
}

/*
 *----------------------------------------------------------------------
 *
 * SerialBlockTime --
 *
 *	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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static unsigned int
SerialGetMilliseconds(void)
{
    Tcl_Time time;

    Tcl_GetTime(&time);

    return (time.sec * 1000 + time.usec / 1000);
}

/*
 *----------------------------------------------------------------------
 *
 * SerialSetupProc --
 *







|






|







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 long long
SerialGetMilliseconds(void)
{
    Tcl_Time time;

    Tcl_GetTime(&time);

    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

#ifdef __cplusplus
#define min(a, b)  (((a) < (b)) ? (a) : (b))
#endif

void
SerialSetupProc(
    TCL_UNUSED(ClientData),
    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);








|







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(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
 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
SerialCheckProc(
    TCL_UNUSED(ClientData),
    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;

    if (!(flags & TCL_FILE_EVENTS)) {
	return;
    }

    /*
     * Queue events for any ready serials that don't already have events







|







|







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(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 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
		     * 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) {
			    needEvent = 1;
			    infoPtr->lastEventTime = time;
			}
		    }
		}
	    }
	}







|
|







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 ((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
 *	Sets the device into blocking or non-blocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
SerialBlockProc(
    ClientData instanceData,    /* Instance data for channel. */
    int mode)			/* TCL_MODE_BLOCKING or
				 * TCL_MODE_NONBLOCKING. */
{
    int errorCode = 0;
    SerialInfo *infoPtr = (SerialInfo *) instanceData;

    /*







|







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(
    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
 *	Closes the physical channel.
 *
 *----------------------------------------------------------------------
 */

static int
SerialCloseProc(
    ClientData 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);







|







596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
 *	Closes the physical channel.
 *
 *----------------------------------------------------------------------
 */

static int
SerialCloseProc(
    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);
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
     */

    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());
	    errorCode = errno;
	}
    }

    serialPtr->watchMask &= serialPtr->validMask;

    /*







|







641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
     */

    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) {
	    Tcl_WinConvertError(GetLastError());
	    errorCode = errno;
	}
    }

    serialPtr->watchMask &= serialPtr->validMask;

    /*
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
     */

    osPtr->Offset = osPtr->OffsetHigh = 0;
    result = WriteFile(infoPtr->handle, buf, bufSize, lpWritten, osPtr);
    LeaveCriticalSection(&infoPtr->csWrite);

    if (result == FALSE) {
	int err = GetLastError();

	switch (err) {
	case ERROR_IO_PENDING:
	    /*
	     * Write is pending, wait for completion.
	     */








|







792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
     */

    osPtr->Offset = osPtr->OffsetHigh = 0;
    result = WriteFile(infoPtr->handle, buf, bufSize, lpWritten, osPtr);
    LeaveCriticalSection(&infoPtr->csWrite);

    if (result == FALSE) {
	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
 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
SerialInputProc(
    ClientData 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;







|







851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
 *	Reads input from the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
SerialInputProc(
    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
		}
	    } else {
		errno = *errorCode = EWOULDBLOCK;
		return -1;
	    }
	} else {
	    /*
	     * BLOCKING mode: Tcl trys 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;
    }

    /*
     * 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());
	*errorCode = errno;
	return -1;
    }
    return bytesRead;

  commError:
    infoPtr->lastError = infoPtr->error;







|













|









|







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 {
		errno = *errorCode = EWOULDBLOCK;
		return -1;
	    }
	} else {
	    /*
	     * 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 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) {
	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
 *	Writes output on the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
SerialOutputProc(
    ClientData 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
     * blocking output after ExitProc or CloseHandler(chan) has been called by
     * checking the corrresponding variables.
     */

    if (!initialized || TclInExit()) {
	return toWrite;
    }

    /*







|










|

|







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
 *	Writes output on the actual channel.
 *
 *----------------------------------------------------------------------
 */

static int
SerialOutputProc(
    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 tries to flush all open channels in blocking mode. We avoid
     * blocking output after ExitProc or CloseHandler(chan) has been called by
     * checking the corresponding variables.
     */

    if (!initialized || TclInExit()) {
	return toWrite;
    }

    /*
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
    }

    /*
     * Check for a background error on the last write.
     */

    if (infoPtr->writeError) {
	TclWinConvertError(infoPtr->writeError);
	infoPtr->writeError = 0;
	goto error1;
    }

    /*
     * Remember the number of bytes in output queue
     */







|







1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
    }

    /*
     * Check for a background error on the last write.
     */

    if (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
	    goto error;
	}
    }

    return (int) bytesWritten;

  writeError:
    TclWinConvertError(GetLastError());

  error:
    /*
     * Reset the output queue counter on error during blocking output
     */

    /*







|







1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
	    goto error;
	}
    }

    return (int) bytesWritten;

  writeError:
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
SerialWatchProc(
    ClientData 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;







|







1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
SerialWatchProc(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
SerialGetHandleProc(
    ClientData instanceData,	/* The serial state. */
    TCL_UNUSED(int) /*direction*/,
    ClientData *handlePtr)	/* Where to store the handle. */
{
    SerialInfo *infoPtr = (SerialInfo *) instanceData;

    *handlePtr = (ClientData) infoPtr->handle;
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * SerialWriterThread --







|

|



|







1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
SerialGetHandleProc(
    void *instanceData,	/* The serial state. */
    TCL_UNUSED(int) /*direction*/,
    void **handlePtr)	/* Where to store the handle. */
{
    SerialInfo *infoPtr = (SerialInfo *) instanceData;

    *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
    SerialInfo *infoPtr;

    SerialInit();

    infoPtr = (SerialInfo *)Tcl_Alloc(sizeof(SerialInfo));
    memset(infoPtr, 0, sizeof(SerialInfo));

    infoPtr->validMask = permissions;
    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);

    infoPtr->channel = Tcl_CreateChannel(&serialChannelType, channelName,
	    infoPtr, permissions);


    SetupComm(handle, infoPtr->sysBufRead, infoPtr->sysBufWrite);
    PurgeComm(handle,
	    PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);







|

















<
|







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
    SerialInfo *infoPtr;

    SerialInit();

    infoPtr = (SerialInfo *)Tcl_Alloc(sizeof(SerialInfo));
    memset(infoPtr, 0, sizeof(SerialInfo));

    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).
     */


    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);
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
	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;
}

/*
 *----------------------------------------------------------------------
 *







<
<
<
<
<

<







1503
1504
1505
1506
1507
1508
1509





1510

1511
1512
1513
1514
1515
1516
1517
	infoPtr->osWrite.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
	infoPtr->evWritable = CreateEventW(NULL, TRUE, TRUE, NULL);
	infoPtr->writeThread = CreateThread(NULL, 256, SerialWriterThread,
		TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr,
			infoPtr->evWritable), 0, NULL);
    }






    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");


    return infoPtr->channel;
}

/*
 *----------------------------------------------------------------------
 *
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
    }
    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);
	Tcl_DStringAppendElement(dsPtr, buf);
    }
}

/*
 *----------------------------------------------------------------------
 *







|







1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
    }
    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];

	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
 *	May modify an option on a device.
 *
 *----------------------------------------------------------------------
 */

static int
SerialSetOptionProc(
    ClientData 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;
    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) {
	    infoPtr->flags &= ~SERIAL_CLOSE_MASK;
	} else if (Tcl_UtfNcasecmp(value, "DRAIN", vlen) == 0) {
	    infoPtr->flags &= ~SERIAL_CLOSE_MASK;
	    infoPtr->flags |= SERIAL_CLOSE_DRAIN;
	} else if (Tcl_UtfNcasecmp(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);
	    }
	    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);
	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);
	    }
	    return TCL_ERROR;
	}

	/*
	 * Default settings for serial communications.
	 */







|










|

















|

|


|








|















|








|







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
 *	May modify an option on a device.
 *
 *----------------------------------------------------------------------
 */

static int
SerialSetOptionProc(
    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;
    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 (strncasecmp(value, "DEFAULT", vlen) == 0) {
	    infoPtr->flags &= ~SERIAL_CLOSE_MASK;
	} else if (strncasecmp(value, "DRAIN", vlen) == 0) {
	    infoPtr->flags &= ~SERIAL_CLOSE_MASK;
	    infoPtr->flags |= SERIAL_CLOSE_DRAIN;
	} 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", (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, 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", (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
	    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);
	    }
	    return TCL_ERROR;
	}

	if (!SetCommState(infoPtr->handle, &dcb)) {
	    goto setStateFailed;
	}







|







1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
	    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", (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
	    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);
	    }
	    Tcl_Free((void *)argv);
	    return TCL_ERROR;
	}

	/*
	 * These dereferences are safe, even in the zero-length string cases,







|
|







1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
	    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", 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

	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);
	    if ((character > 0xFF) || argv[0][charLen]) {
		goto badXchar;
	    }
	    dcb.XonChar = (char) character;
	    charLen = Tcl_UtfToUniChar(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)) {

	int i, 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_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));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION",
				"FCONFIGURE", "TTY_SIGNAL", 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));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION",
				"FCONFIGURE", "TTY_SIGNAL", 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));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION",
				"FCONFIGURE", "TTY_SIGNAL", 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);
		}
		res = TCL_ERROR;
		break;
	    }
	}

	Tcl_Free((void *)argv);







|




|


















>
|









|















|

|









|

|









|

|










|







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

	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 = TclUtfToUniChar(argv[0], &character);
	    if ((character > 0xFF) || argv[0][charLen]) {
		goto badXchar;
	    }
	    dcb.XonChar = (char) 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 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", (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", TCL_INDEX_NONE));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION",
				"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", TCL_INDEX_NONE));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION",
				"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", TCL_INDEX_NONE));
			Tcl_SetErrorCode(interp, "TCL", "OPERATION",
				"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",
			    (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
	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);
	    }
	    return TCL_ERROR;
	}

	if (!SetupComm(infoPtr->handle, inSize, outSize)) {
	    if (interp != NULL) {
		TclWinConvertError(GetLastError());
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't setup comm buffers: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	infoPtr->sysBufRead  = inSize;







|






|







1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
	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", (char *)NULL);
	    }
	    return TCL_ERROR;
	}

	if (!SetupComm(infoPtr->handle, inSize, outSize)) {
	    if (interp != NULL) {
		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

	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_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_SetObjResult(interp, Tcl_ObjPrintf(
		"can't get comm state: %s", Tcl_PosixError(interp)));
    }
    return TCL_ERROR;

  setStateFailed:
    if (interp != NULL) {
	TclWinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't set comm state: %s", Tcl_PosixError(interp)));
    }
    return TCL_ERROR;
}

/*







|
















|







|







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

	if (Tcl_GetInt(interp, value, &msec) != TCL_OK) {
	    return TCL_ERROR;
	}
	tout.ReadTotalTimeoutConstant = msec;
	if (!SetCommTimeouts(infoPtr->handle, &tout)) {
	    if (interp != NULL) {
		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) {
	Tcl_WinConvertError(GetLastError());
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't get comm state: %s", Tcl_PosixError(interp)));
    }
    return TCL_ERROR;

  setStateFailed:
    if (interp != NULL) {
	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
 *	reused at any time subsequent to the call.
 *
 *----------------------------------------------------------------------
 */

static int
SerialGetOptionProc(
    ClientData 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;







|







2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
 *	reused at any time subsequent to the call.
 *
 *----------------------------------------------------------------------
 */

static int
SerialGetOptionProc(
    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
    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_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,
		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);
	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);
	Tcl_DStringAppendElement(dsPtr, buf);
	wsprintfA(buf, "%d", 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_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);







|














|















|















|

|




















|







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
    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) {
		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";

	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;
	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;

	snprintf(buf, sizeof(buf), "%ld", infoPtr->sysBufRead);
	Tcl_DStringAppendElement(dsPtr, buf);
	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) {
		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
	 */

	EnterCriticalSection(&infoPtr->csWrite);
	ClearCommError(infoPtr->handle, &error, &cStat);
	count = (int) cStat.cbOutQue + infoPtr->writeQueue;
	LeaveCriticalSection(&infoPtr->csWrite);

	wsprintfA(buf, "%d", inBuffered + cStat.cbInQue);
	Tcl_DStringAppendElement(dsPtr, buf);
	wsprintfA(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_SetObjResult(interp, Tcl_ObjPrintf(
			"can't get tty status: %s", Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	valid = 1;
	SerialModemStatusStr(status, dsPtr);







|

|















|







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
	 */

	EnterCriticalSection(&infoPtr->csWrite);
	ClearCommError(infoPtr->handle, &error, &cStat);
	count = (int) cStat.cbOutQue + infoPtr->writeQueue;
	LeaveCriticalSection(&infoPtr->csWrite);

	snprintf(buf, sizeof(buf), "%ld", inBuffered + cStat.cbInQue);
	Tcl_DStringAppendElement(dsPtr, buf);
	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) {
		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
 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
SerialThreadActionProc(
    ClientData 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
     * this structure.
     */

    Tcl_MutexLock(&serialMutex);
    if (action == TCL_CHANNEL_THREAD_INSERT) {
	/*
	 * We can't copy the thread information from the channel when the







|







|







2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
SerialThreadActionProc(
    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 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
/*
 * tclWinSock.c --
 *
 *	This file contains Windows-specific socket related code.
 *
 * Copyright (c) 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.





|







1
2
3
4
5
6
7
8
9
10
11
12
13
/*
 * tclWinSock.c --
 *
 *	This file contains Windows-specific socket related code.
 *
 * 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

#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)

/* "sock" + a pointer in hex + \0 */
#define SOCK_CHAN_LENGTH        (4 + sizeof(void *) * 2 + 1)
#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).
 */








<
<
<
<
<
<
<











|
<







50
51
52
53
54
55
56







57
58
59
60
61
62
63
64
65
66
67
68

69
70
71
72
73
74
75

#include "tclWinInt.h"

#ifdef _MSC_VER
#   pragma comment (lib, "ws2_32")
#endif








/*
 * 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        (16 + TCL_INTEGER_SPACE)


/*
 * 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).
 */

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
} 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.
 */

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. */

    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. */

    /*
     * 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. */
    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
 * structure.
 */

#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
					 * socket. */
#define SOCKET_PENDING		(1<<3)	/* A message has been sent for this
					 * socket */
#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
					 * automatically continue connection
					 * process */

/*
 * The following structure is what is added to the Tcl event queue when a
 * socket event occurs.
 */







|












<
<
<


>



















|




















|















<
<
<
<
<
|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178





179
180
181
182
183
184
185
186
} 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.
 */

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 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. */
    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. */
    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 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 SOCKET_EOF		(1<<2)	/* A zero read happened on the
					 * socket. */
#define SOCKET_PENDING		(1<<3)	/* A message has been sent for this
					 * socket */
#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 */






#define 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.
 */
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

/*
 * Static routines for this file:
 */

static int		TcpConnect(Tcl_Interp *interp,
			    TcpState *state);
static void		InitSockets(void);
static TcpState *	NewSocketInfo(SOCKET socket);
static void		SocketExitHandler(ClientData 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 int		FindFDInList(TcpState *statePtr, SOCKET socket);
static DWORD WINAPI	SocketThread(LPVOID arg);
static void		TcpThreadActionProc(ClientData 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;







|

|


<







|







224
225
226
227
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

/*
 * Static routines for this file:
 */

static int		TcpConnect(Tcl_Interp *interp,
			    TcpState *state);
static void		InitSocketWindowClass(void);
static TcpState *	NewSocketInfo(SOCKET socket);
static void		SocketExitHandler(void *clientData);
static LRESULT CALLBACK	SocketProc(HWND hwnd, UINT message, WPARAM wParam,
			    LPARAM lParam);

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 int		FindFDInList(TcpState *statePtr, SOCKET socket);
static DWORD WINAPI	SocketThread(LPVOID arg);
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;
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
 * 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. */







|







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
 * 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. */
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

    Tcl_DStringInit(&ds);
    if (GetComputerNameExW(ComputerNamePhysicalDnsFullyQualified, wbuf, &length) != 0) {
	/*
	 * Convert string from native to UTF then change to lowercase.
	 */

	Tcl_UtfToLower(Tcl_WCharToUtfDString(wbuf, -1, &ds));

    } else {
	if (TclpHasSockets(NULL) == TCL_OK) {
	    /*
	     * 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_DStringLength(&inDs)) == 0) {
		Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&inDs), -1,
			&ds);
	    }
	    Tcl_DStringFree(&inDs);
	}
    }

    *encodingPtr = Tcl_GetEncoding(NULL, "utf-8");
    *lengthPtr = Tcl_DStringLength(&ds);
    *valuePtr = (char *)Tcl_Alloc(*lengthPtr + 1);
    memcpy(*valuePtr, Tcl_DStringValue(&ds), *lengthPtr + 1);
    Tcl_DStringFree(&ds);







|


|
|
|
|
|

|

|
|
|
|
|
|
|
|
<







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

    Tcl_DStringInit(&ds);
    if (GetComputerNameExW(ComputerNamePhysicalDnsFullyQualified, wbuf, &length) != 0) {
	/*
	 * Convert string from native to UTF then change to lowercase.
	 */

	Tcl_UtfToLower(Tcl_WCharToUtfDString(wbuf, TCL_INDEX_NONE, &ds));

    } else {
	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_DStringLength(&inDs)) == 0) {
	    Tcl_ExternalToUtfDStringEx(NULL, NULL, Tcl_DStringValue(&inDs),
		    TCL_INDEX_NONE, TCL_ENCODING_PROFILE_TCL8, &ds, NULL);
	}
	Tcl_DStringFree(&inDs);

    }

    *encodingPtr = Tcl_GetEncoding(NULL, "utf-8");
    *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
{
    return Tcl_GetString(TclGetProcessGlobalValue(&hostName));
}

/*
 *----------------------------------------------------------------------
 *
 * TclpHasSockets --
 *
 *	This function determines whether sockets are available on the current
 *	system and returns an error in interp if they are not. Note that
 *	interp may be NULL.
 *
 * Results:
 *	Returns TCL_OK if the system supports sockets, or TCL_ERROR with an
 *	error in interp (if non-NULL).

 *
 * 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(
    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);








    if (SocketsEnabled()) {




	return TCL_OK;
    }









    if (interp != NULL) {

	Tcl_SetObjResult(interp, Tcl_NewStringObj(




		"sockets are not available on this system", -1));

    }


    return TCL_ERROR;





}

/*
 *----------------------------------------------------------------------
 *
 * TclpFinalizeSockets --
 *







|

|
|
<


<
<
>









|
|
<
>
|
|
>
|
>
>
>
|
|
|
>
>
>
>
>

>
>
|
>
>
>
>
|

>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
|
>
|
>
>
|
>
>
>
>
>







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
{
    return Tcl_GetString(TclGetProcessGlobalValue(&hostName));
}

/*
 *----------------------------------------------------------------------
 *
 * TclInitSockets --
 *
 *     Initialization of sockets for the thread. Also creates message
 *     handling window class for the process if needed.

 *
 * Results:


 *	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.
 *
 *----------------------------------------------------------------------
 */

void
TclInitSockets(void)

{
    /* 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;
    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) {
	Tcl_CreateEventSource(SocketSetupProc, SocketCheckProc, NULL);
	return;
    }

  initFailure:
    Tcl_Panic("InitSockets failed");
    return;
}

/*
 *----------------------------------------------------------------------
 *
 * TclpFinalizeSockets --
 *
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
 *	Sets the device into blocking or nonblocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
TcpBlockModeProc(
    ClientData 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);
    }
    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
 *	    return any error code.
 *
 * Results:
 * 	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.
 *
 *----------------------------------------------------------------------
 */

static int
WaitForConnect(
    TcpState *statePtr,		/* State of the socket. */







|









|




















|
|








|







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
 *	Sets the device into blocking or nonblocking mode.
 *
 *----------------------------------------------------------------------
 */

static int
TcpBlockModeProc(
    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);
    }
    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 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.
 *
 * Side effects:
 *	Processes socket events off the system queue. May process
 *	asynchronous connect.
 *
 *----------------------------------------------------------------------
 */

static int
WaitForConnect(
    TcpState *statePtr,		/* State of the socket. */
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
     * 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)
	    && errorCodePtr != NULL
            && GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
	*errorCodePtr = EWOULDBLOCK;
	return -1;
    }

    /*







|







640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
     * 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->flags, TCP_ASYNC_TEST_MODE)
	    && errorCodePtr != NULL
            && GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
	*errorCodePtr = EWOULDBLOCK;
	return -1;
    }

    /*
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
	 * Get the statePtr lock.
	 */

	tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	/*
         * Check for connect event.
         */

	if (GOT_BITS(statePtr->readyEvents, FD_CONNECT)) {
	    /*
             * Consume the connect event.
             */

	    CLEAR_BITS(statePtr->readyEvents, FD_CONNECT);

	    /*
	     * For blocking sockets and foreground processing, disable async
	     * connect as we continue now synchoneously.
	     */

	    if (errorCodePtr != NULL &&
		    !GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
		CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);
	    }

	    /*
             * Free list lock.
             */

	    SetEvent(tsdPtr->socketListLock);

	    /*
	     * Continue connect. If switched to synchroneous connect, the
	     * connect is terminated.
	     */

	    result = TcpConnect(NULL, statePtr);

	    /*
             * Restore event service mode.
             */

	    (void) Tcl_SetServiceMode(oldMode);

	    /*
	     * Check for Succesfull connect or async connect restart
	     */

	    if (result == TCL_OK) {
		/*
		 * Check for async connect restart (not possible for
		 * foreground blocking operation)
		 */







|
|



|
|





|








|
|




|






|
|




|







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
	 * Get the statePtr lock.
	 */

	tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);
	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	/*
	 * Check for connect event.
	 */

	if (GOT_BITS(statePtr->readyEvents, FD_CONNECT)) {
	    /*
	     * Consume the connect event.
	     */

	    CLEAR_BITS(statePtr->readyEvents, FD_CONNECT);

	    /*
	     * For blocking sockets and foreground processing, disable async
	     * 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.
	     */

	    SetEvent(tsdPtr->socketListLock);

	    /*
	     * Continue connect. If switched to synchronous connect, the
	     * connect is terminated.
	     */

	    result = TcpConnect(NULL, statePtr);

	    /*
	     * Restore event service mode.
	     */

	    (void) Tcl_SetServiceMode(oldMode);

	    /*
	     * Check for Successful connect or async connect restart
	     */

	    if (result == TCL_OK) {
		/*
		 * Check for async connect restart (not possible for
		 * foreground blocking operation)
		 */
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
 *	Reads input from the input device of the channel.
 *
 *----------------------------------------------------------------------
 */

static int
TcpInputProc(
    ClientData 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);

    *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;







|












<
<
<
<
<
<
<
<
<
<
<







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
 *	Reads input from the input device of the channel.
 *
 *----------------------------------------------------------------------
 */

static int
TcpInputProc(
    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);

    *errorCodePtr = 0;












    /*
     * 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
     * using non-blocking sockets.
     */

    while (1) {
	SendSelectMessage(tsdPtr, UNSELECT, statePtr);

	/*
         * 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.
	 */







|
|
|







833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
     * using non-blocking sockets.
     */

    while (1) {
	SendSelectMessage(tsdPtr, UNSELECT, statePtr);

	/*
	 * 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
	    break;
	}

	error = WSAGetLastError();

	/*
	 * If an RST comes, then ignore the error and report an EOF just like
	 * 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);
	    *errorCodePtr = Tcl_GetErrno();
	    bytesRead = -1;
	    break;
	}

	/*
	 * In the blocking case, wait until the file becomes readable or







|













|
|







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
	    break;
	}

	error = WSAGetLastError();

	/*
	 * If an RST comes, then ignore the error and report an EOF just like
	 * 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)) {
	    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
 *	Produces output on the socket.
 *
 *----------------------------------------------------------------------
 */

static int
TcpOutputProc(
    ClientData 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);

    *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.
         */

	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.







|











<
<
<
<
<
<
<
<
<
<
<














|
|
|







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
 *	Produces output on the socket.
 *
 *----------------------------------------------------------------------
 */

static int
TcpOutputProc(
    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);

    *errorCodePtr = 0;












    /*
     * 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.
	 */

	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
	    CLEAR_BITS(statePtr->readyEvents, FD_WRITE);
	    if (GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
		*errorCodePtr = EWOULDBLOCK;
		written = -1;
		break;
	    }
	} else {
	    TclWinConvertError(error);
	    *errorCodePtr = Tcl_GetErrno();
	    written = -1;
	    break;
	}

	/*
	 * In the blocking case, wait until the file becomes writable or







|







984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
	    CLEAR_BITS(statePtr->readyEvents, FD_WRITE);
	    if (GOT_BITS(statePtr->flags, TCP_NONBLOCKING)) {
		*errorCodePtr = EWOULDBLOCK;
		written = -1;
		break;
	    }
	} else {
	    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
 *	Closes the socket.
 *
 *----------------------------------------------------------------------
 */

static int
TcpCloseProc(
    ClientData 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.
	 */

	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);
	}
    }

    if (statePtr->addrlist != NULL) {
        freeaddrinfo(statePtr->addrlist);
    }
    if (statePtr->myaddrlist != NULL) {
        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.
         */

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	tsdPtr->pendingTcpState = NULL;

	/*
         * 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







|








<
<
<
<
<
<
<
|
|
|
|

|
|

|
|
|
|
|
|
<



















|
|






|
|







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
 *	Closes the socket.
 *
 *----------------------------------------------------------------------
 */

static int
TcpCloseProc(
    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);

    /*







     * 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;

	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);
    }
    if (statePtr->myaddrlist != NULL) {
        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.
	 */

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	tsdPtr->pendingTcpState = NULL;

	/*
	 * 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
 *	Shuts down one side of the socket.
 *
 *----------------------------------------------------------------------
 */

static int
TcpClose2Proc(
    ClientData 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;








|







1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
 *	Shuts down one side of the socket.
 *
 *----------------------------------------------------------------------
 */

static int
TcpClose2Proc(
    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;

1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164

    /*
     * 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) && (shutdown(statePtr->sockets->fd, SD_RECEIVE) == SOCKET_ERROR)) {
	TclWinConvertError((DWORD) WSAGetLastError());
	readError = Tcl_GetErrno();
    }
    if ((flags & TCL_CLOSE_WRITE) && (shutdown(statePtr->sockets->fd, SD_SEND) == SOCKET_ERROR)) {
	TclWinConvertError((DWORD) WSAGetLastError());
	writeError = Tcl_GetErrno();
    }
    return (readError != 0) ? readError : writeError;
}

/*
 *----------------------------------------------------------------------







|



|







1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152

    /*
     * 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) && (shutdown(statePtr->sockets->fd, SD_RECEIVE) == SOCKET_ERROR)) {
	Tcl_WinConvertError((DWORD) WSAGetLastError());
	readError = Tcl_GetErrno();
    }
    if ((flags & TCL_CLOSE_WRITE) && (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
 *	Changes attributes of the socket at the system level.
 *
 *----------------------------------------------------------------------
 */

static int
TcpSetOptionProc(
    ClientData 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. */
{
#ifdef TCL_FEATURE_KEEPALIVE_NAGLE
    TcpState *statePtr = instanceData;
    SOCKET sock;
#else
    (void)instanceData;
#endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/

    /*
     * 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) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "winsock is not initialized", -1));
	}
	return TCL_ERROR;
    }

#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 (!strcasecmp(optionName, "-keepalive")) {
	BOOL val = FALSE;
	int boolVar, 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));
	if (rtn != 0) {
	    TclWinConvertError(WSAGetLastError());
	    if (interp) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"couldn't set socket option: %s",
			Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;
	}
	return TCL_OK;


    } else if (!strcasecmp(optionName, "-nagle")) {
	BOOL val = FALSE;
	int boolVar, 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));
	if (rtn != 0) {
	    TclWinConvertError(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");
#else
    return Tcl_BadChannelOption(interp, optionName, "");
#endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/
}

/*
 *----------------------------------------------------------------------
 *
 * TcpGetOptionProc --
 *







|


|

<
|

<
<
<
|
<
<
<
<
<

<
|
<
<
<
|


<
<


>
|
|
|




<
<
<

|

|








>
>
|
|
|




<
<
<

|

|









<
|
<
<
<







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
 *	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;
    SOCKET sock;



    size_t len = 0;







    if (optionName != NULL) {



	len = strlen(optionName);
    }



    sock = statePtr->sockets->fd;

    if ((len > 1) && (optionName[1] == 'k') &&
	    (strncmp(optionName, "-keepalive", len) == 0)) {
	BOOL boolVar;
	int rtn;

	if (Tcl_GetBoolean(interp, value, &boolVar) != TCL_OK) {
	    return TCL_ERROR;
	}



	rtn = setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
		(const char *) &boolVar, sizeof(boolVar));
	if (rtn != 0) {
	    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') &&
	    (strncmp(optionName, "-nodelay", len) == 0)) {
	BOOL boolVar;
	int rtn;

	if (Tcl_GetBoolean(interp, value, &boolVar) != TCL_OK) {
	    return TCL_ERROR;
	}



	rtn = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
		(const char *) &boolVar, sizeof(boolVar));
	if (rtn != 0) {
	    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 nodelay");



}

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TcpGetOptionProc(
    ClientData 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"

    /*
     * 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) {
	    Tcl_SetObjResult(interp, Tcl_NewStringObj(
		    "winsock is not initialized", -1));
	}
	return TCL_ERROR;
    }

    /*
     * Go one step in async connect
     *
     * If any error is thrown save it as backround error to report eventually
     * below.
     */

    if (!GOT_BITS(statePtr->testFlags, 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)) {
	/*
         * 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);
		    statePtr->connectError = 0;
		}
	    } else {
		/*
		 * Report an eventual last error of the socket system.
		 */








|














<
<
<
<
<
<
<
<
<
<
<
<
<
<



|



|











|
|











|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TcpGetOptionProc(
    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"















    /*
     * Go one step in async connect
     *
     * If any error is thrown save it as background error to report eventually
     * below.
     */

    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)) {
	/*
	 * 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), 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
		}

		/*
		 * Return error message.
		 */

		if (err) {
		    TclWinConvertError(err);
		    Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()),
                            -1);
		}
	    }
	}
	return TCL_OK;
    }

    if ((len > 1) && (optionName[1] == 'c') &&
	    (strncmp(optionName, "-connecting", len) == 0)) {
	Tcl_DStringAppend(dsPtr,
		GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)
		? "1" : "0", -1);
        return TCL_OK;
    }

    if (interp != NULL
            && Tcl_GetVar2(interp, SUPPRESS_RDNS_VAR, NULL, 0) != NULL) {
	reverseDNS = NI_NUMERICHOST;
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (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) {
	    /*
	     * Peername fetch succeeded - output list
	     */

	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringStartSublist(dsPtr);







|
|
<










|




|




















|







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
		}

		/*
		 * Return error message.
		 */

		if (err) {
		    Tcl_WinConvertError(err);
		    Tcl_DStringAppend(dsPtr, Tcl_ErrnoMsg(Tcl_GetErrno()), TCL_INDEX_NONE);

		}
	    }
	}
	return TCL_OK;
    }

    if ((len > 1) && (optionName[1] == 'c') &&
	    (strncmp(optionName, "-connecting", len) == 0)) {
	Tcl_DStringAppend(dsPtr,
		GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)
		? "1" : "0", TCL_INDEX_NONE);
        return TCL_OK;
    }

    if (interp != NULL
	    && Tcl_GetVar(interp, SUPPRESS_RDNS_VAR, 0) != NULL) {
	reverseDNS = NI_NUMERICHOST;
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (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) {
	    /*
	     * 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
	     * 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());
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "can't get peername: %s",
			    Tcl_PosixError(interp)));
		}
		return TCL_ERROR;
	    }







|







1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
	     * 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) {
		Tcl_WinConvertError((DWORD) WSAGetLastError());
		if (interp) {
		    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			    "can't get peername: %s",
			    Tcl_PosixError(interp)));
		}
		return TCL_ERROR;
	    }
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
	    Tcl_DStringStartSublist(dsPtr);
	}
	if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
	    /*
	     * In async connect output an empty string
	     */

            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;








|







1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
	    Tcl_DStringStartSublist(dsPtr);
	}
	if (GOT_BITS(statePtr->flags, TCP_ASYNC_PENDING)) {
	    /*
	     * In async connect output an empty string
	     */

	    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
	if (found) {
	    if (len) {
		return TCL_OK;
	    }
	    Tcl_DStringEndSublist(dsPtr);
	} else {
	    if (interp) {
		TclWinConvertError((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)) {
	int optlen;
	BOOL opt = FALSE;

	if (len == 0) {

	    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");
	}



	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) {
	    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");
#endif /*TCL_FEATURE_KEEPALIVE_NAGLE*/
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|







|
|




>




<
|
>
>
>
>
|
>
>
>
>
>
>
>
|

>
>
>





<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<

<
<
<
|
<







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
	if (found) {
	    if (len) {
		return TCL_OK;
	    }
	    Tcl_DStringEndSublist(dsPtr);
	} else {
	    if (interp) {
		Tcl_WinConvertError((DWORD) WSAGetLastError());
		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 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);

	Tcl_DStringAppendElement(dsPtr, opt ? "1" : "0");
	if (len > 0) {
	    return TCL_OK;
	}
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'n') &&
	    (strncmp(optionName, "-nodelay", len) == 0))) {
	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) {







	return Tcl_BadChannelOption(interp, optionName,



		"connecting keepalive nodelay peername sockname");

    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
 *	already true.
 *
 *----------------------------------------------------------------------
 */

static void
TcpWatchProc(
    ClientData 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;

    /*







|







1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
 *	already true.
 *
 *----------------------------------------------------------------------
 */

static void
TcpWatchProc(
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TcpGetHandleProc(
    ClientData instanceData,	/* The socket state. */
    TCL_UNUSED(int) /*direction*/,
    ClientData *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.







|

|






<
<







1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610


1611
1612
1613
1614
1615
1616
1617
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TcpGetHandleProc(
    void *instanceData,	/* The socket state. */
    TCL_UNUSED(int) /*direction*/,
    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.
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

    if (async_callback) {
        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) {
	    /*
	     * 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.
             */

	    if (statePtr->sockets->fd != INVALID_SOCKET) {
		closesocket(statePtr->sockets->fd);
	    }

	    /*
             * 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);

	    /*
             * Free list lock.
             */

	    SetEvent(tsdPtr->socketListLock);

	    /*
             * Continue on socket creation error.
             */

	    if (statePtr->sockets->fd == INVALID_SOCKET) {
		TclWinConvertError((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);

	    /*
	     * Set kernel space buffering
	     */

	    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());
		continue;
	    }

	    /*
	     * For asynchroneous connect set the socket in nonblocking mode
	     * and activate connect notification
	     */

	    if (async_connect) {
		TcpState *statePtr2;
		int in_socket_list = 0;

		/*
                 * 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







|
|
|



















|
|











|


|
|




|
|


|









|





|
|







|




|








|
|







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

    if (async_callback) {
        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) {
	    /*
	     * 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.
             */

	    if (statePtr->sockets->fd != INVALID_SOCKET) {
		closesocket(statePtr->sockets->fd);
	    }

	    /*
	     * 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);

	    /*
	     * Free list lock.
	     */

	    SetEvent(tsdPtr->socketListLock);

	    /*
	     * Continue on socket creation error.
	     */

	    if (statePtr->sockets->fd == INVALID_SOCKET) {
		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);

	    /*
	     * Set kernel space buffering
	     */

	    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) {
		Tcl_WinConvertError((DWORD) WSAGetLastError());
		continue;
	    }

	    /*
	     * 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.
		 */

		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
		}
		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.
                 */

		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);

	    if (async_connect && error == WSAEWOULDBLOCK) {
		/*
		 * Asynchroneous 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.
                 */

		WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

		/*
                 * Get signaled connect error.
                 */

		TclWinConvertError((DWORD) statePtr->notifierConnectError);

		/*
                 * Clear eventual connect flag.
                 */

		CLEAR_BITS(statePtr->selectEvents, FD_CONNECT);

		/*
                 * Free list lock.
                 */

		SetEvent(tsdPtr->socketListLock);
	    }

	    /*
	     * Clear the tsd socket list pointer if we did not wait for
	     * the FD_CONNECT asynchroneously
	     */

	    tsdPtr->pendingTcpState = NULL;

	    if (Tcl_GetErrno() == 0) {
		goto out;
	    }







|












|
|
|












|



|


















|
|




|
|

|


|
|




|
|






|







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
		}
		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.
		 */

		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();
	    Tcl_WinConvertError(error);

	    if (async_connect && error == WSAEWOULDBLOCK) {
		/*
		 * 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.
		 */

		WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

		/*
		 * Get signaled connect error.
		 */

		Tcl_WinConvertError((DWORD) statePtr->notifierConnectError);

		/*
		 * Clear eventual connect flag.
		 */

		CLEAR_BITS(statePtr->selectEvents, FD_CONNECT);

		/*
		 * Free list lock.
		 */

		SetEvent(tsdPtr->socketListLock);
	    }

	    /*
	     * Clear the tsd socket list pointer if we did not wait for
	     * 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
     * Async connect terminated
     */

    CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);

    if (Tcl_GetErrno() == 0) {
	/*
	 * Succesfully connected
	 *
	 * Set up the select mask for read/write events.
	 */

	statePtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE;

	/*







|







1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
     * Async connect terminated
     */

    CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT);

    if (Tcl_GetErrno() == 0) {
	/*
	 * 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
	    /*
	     * Set up the select mask for read/write events.
	     */

	    statePtr->selectEvents = FD_WRITE|FD_READ;

	    /*
             * Get statePtr lock.
             */

	    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	    /*
             * Signal ready readable and writable events.
             */

	    SET_BITS(statePtr->readyEvents, FD_WRITE | FD_READ);

	    /*
             * Flag error to event routine.
             */

	    SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);

	    /*
             * Save connect error to be reported by 'fconfigure -error'.
             */

	    statePtr->connectError = Tcl_GetErrno();

	    /*
             * Free list lock.
             */

	    SetEvent(tsdPtr->socketListLock);
	}

	/*
	 * Error message on synchroneous connect
	 */

	if (interp != NULL) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "couldn't open socket: %s", Tcl_PosixError(interp)));
	}
	return TCL_ERROR;







|
|




|
|




|
|




|
|




|
|





|







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
	    /*
	     * Set up the select mask for read/write events.
	     */

	    statePtr->selectEvents = FD_WRITE|FD_READ;

	    /*
	     * Get statePtr lock.
	     */

	    WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	    /*
	     * Signal ready readable and writable events.
	     */

	    SET_BITS(statePtr->readyEvents, FD_WRITE | FD_READ);

	    /*
	     * Flag error to event routine.
	     */

	    SET_BITS(statePtr->flags, TCP_ASYNC_FAILED);

	    /*
	     * Save connect error to be reported by 'fconfigure -error'.
	     */

	    statePtr->connectError = Tcl_GetErrno();

	    /*
	     * Free list lock.
	     */

	    SetEvent(tsdPtr->socketListLock);
	}

	/*
	 * 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
				 * 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()) {
	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,







<
<
<
<
<
<
<
<
<
<
|
<
<







1983
1984
1985
1986
1987
1988
1989










1990


1991
1992
1993
1994
1995
1996
1997
				 * connect. */
{
    TcpState *statePtr;
    const char *errorMsg = NULL;
    struct addrinfo *addrlist = NULL, *myaddrlist = NULL;
    char channelName[SOCK_CHAN_LENGTH];











    TclInitSockets();



    /*
     * Do the name lookups for the local and remote addresses.
     */

    if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg)
            || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
     * 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);

    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,







<
|







2017
2018
2019
2020
2021
2022
2023

2024
2025
2026
2027
2028
2029
2030
2031
     * Create a new client socket and wrap it in a channel.
     */
    if (TcpConnect(interp, statePtr) != TCL_OK) {
	TcpCloseProc(statePtr, NULL);
	return NULL;
    }


    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_MakeTcpClientChannel(
    ClientData sock)		/* The socket to wrap up into a channel. */
{
    TcpState *statePtr;
    char channelName[SOCK_CHAN_LENGTH];
    ThreadSpecificData *tsdPtr;

    if (TclpHasSockets(NULL) != TCL_OK) {
	return NULL;
    }

    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

    /*
     * Set kernel space buffering and non-blocking.
     */

    TclSockMinimumBuffers(sock, TCP_BUFFER_SIZE);

    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);
    statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName,
	    statePtr, (TCL_READABLE | TCL_WRITABLE));
    Tcl_SetChannelOption(NULL, statePtr->channel, "-translation", "auto crlf");
    return statePtr->channel;
}

/*







|





|
<
<


















|







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
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_Channel
Tcl_MakeTcpClientChannel(
    void *sock)			/* The socket to wrap up into a channel. */
{
    TcpState *statePtr;
    char channelName[SOCK_CHAN_LENGTH];
    ThreadSpecificData *tsdPtr;

    TclInitSockets();



    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

    /*
     * Set kernel space buffering and non-blocking.
     */

    TclSockMinimumBuffers(sock, TCP_BUFFER_SIZE);

    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);

    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

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. */


    Tcl_TcpAcceptProc *acceptProc,
				/* Callback for accepting connections from new
				 * clients. */
    ClientData 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()) {
	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)) {
	goto error;
    }

    for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) {
	sock = socket(addrPtr->ai_family, addrPtr->ai_socktype,
                addrPtr->ai_protocol);
	if (sock == INVALID_SOCKET) {
	    TclWinConvertError((DWORD) WSAGetLastError());
	    continue;
	}

	/*
	 * Win-NT has a misfeature that sockets are inherited in child
	 * processes by default. Turn off the inherit bit.
	 */







>
>



|











<
<
<
<
<
<
<
<
<
<
|
<
<











|







|







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

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. */
    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;











    TclInitSockets();



    /*
     * 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)) {
	goto error;
    }

    for (addrPtr = addrlist; addrPtr != NULL; addrPtr = addrPtr->ai_next) {
	sock = socket(addrPtr->ai_family, addrPtr->ai_socktype,
                addrPtr->ai_protocol);
	if (sock == INVALID_SOCKET) {
	    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
	 *
	 * 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());
	    closesocket(sock);
	    continue;
	}
	if (port == 0 && chosenport == 0) {
	    address sockname;
	    socklen_t namelen = sizeof(sockname);








|
|







2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
	 *
	 * 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) {
	    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

	/*
	 * 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 (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
	    TclWinConvertError((DWORD) WSAGetLastError());
	    closesocket(sock);
	    continue;
	}

	if (statePtr == NULL) {
	    /*
	     * Add this socket to the global list of sockets.







>
>
>
|
|







2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235

	/*
	 * 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, backlog) == SOCKET_ERROR) {
	    Tcl_WinConvertError((DWORD) WSAGetLastError());
	    closesocket(sock);
	    continue;
	}

	if (statePtr == NULL) {
	    /*
	     * Add this socket to the global list of sockets.
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
    }

    if (statePtr != NULL) {
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

	statePtr->acceptProc = acceptProc;
	statePtr->acceptProcData = acceptProcData;
	sprintf(channelName, SOCK_TEMPLATE, 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_CloseEx(NULL, statePtr->channel, 0);
	    return NULL;
	}
	return statePtr->channel;
    }

    if (interp != NULL) {







|
















|







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
    }

    if (statePtr != NULL) {
	ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);

	statePtr->acceptProc = acceptProc;
	statePtr->acceptProcData = acceptProcData;
	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_CloseEx(NULL, statePtr->channel, 0);
	    return NULL;
	}
	return statePtr->channel;
    }

    if (interp != NULL) {
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
 *	connection acceptance mechanism.
 *
 *----------------------------------------------------------------------
 */

static void
TcpAccept(
    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);







|
|
|







2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
 *	connection acceptance mechanism.
 *
 *----------------------------------------------------------------------
 */

static void
TcpAccept(
    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);
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
    /*
     * 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);
    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);
	statePtr->acceptProc(statePtr->acceptProcData, newInfoPtr->channel,
			    host, atoi(port));
    }
}

/*
 *----------------------------------------------------------------------
 *
 * InitSockets --
 *
 *	Registers the event window for the socket notifier code.
 *
 *	Assumes socketMutex is held.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Register a new window class and creates a
 *	window for use in asynchronous socket notification.
 *
 *----------------------------------------------------------------------
 */

static void
InitSockets(void)
{
    DWORD id;
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);


    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







|



















|

|






|

|
<
|





|
<





|

|
|
|
>







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
    /*
     * Select on read/write events and create the channel.
     */

    newInfoPtr->selectEvents = (FD_READ | FD_WRITE | FD_CLOSE);
    SendSelectMessage(tsdPtr, SELECT, 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);
	statePtr->acceptProc(statePtr->acceptProcData, newInfoPtr->channel,
		host, atoi(port));
    }
}

/*
 *----------------------------------------------------------------------
 *
 * InitSocketWindowClass --
 *
 *	Registers the event window class for the socket notifier code.

 *	Caller must not hold socket mutex lock.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	Register a new window class.

 *
 *----------------------------------------------------------------------
 */

static void
InitSocketWindowClass(void)
{
    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
	windowClass.lpszMenuName = NULL;
	windowClass.lpszClassName = className;
	windowClass.lpfnWndProc = SocketProc;
	windowClass.hIcon = NULL;
	windowClass.hCursor = NULL;

	if (!RegisterClassW(&windowClass)) {
	    TclWinConvertError(GetLastError());
	    goto initFailure;
	}
    }

    /*
     * Check for per-thread initialization.
     */

    if (tsdPtr != NULL) {
	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);
    return enabled;

}


/*
 *----------------------------------------------------------------------
 *
 * 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_MutexLock(&socketMutex);

    /*
     * Make sure the socket event handling window is cleaned-up for, at
     * most, this thread.
     */







|



|
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
>

<




















|







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
	windowClass.lpszMenuName = NULL;
	windowClass.lpszClassName = className;
	windowClass.lpfnWndProc = SocketProc;
	windowClass.hIcon = NULL;
	windowClass.hCursor = NULL;

	if (!RegisterClassW(&windowClass)) {
	    Tcl_WinConvertError(GetLastError());
	    goto initFailure;
	}
    }
    Tcl_MutexUnlock(&socketMutex);





    return;











































  initFailure:

































    Tcl_MutexUnlock(&socketMutex); /* Probably pointless before panicing */

    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(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
 *	Adjusts the block time if needed.
 *
 *----------------------------------------------------------------------
 */

void
SocketSetupProc(
    TCL_UNUSED(ClientData),
    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)) {
	    Tcl_SetMaxBlockTime(&blockTime);
	    break;
	}
    }
    SetEvent(tsdPtr->socketListLock);
}








|

















|







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
 *	Adjusts the block time if needed.
 *
 *----------------------------------------------------------------------
 */

void
SocketSetupProc(
    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)) {
	    Tcl_SetMaxBlockTime(&blockTime);
	    break;
	}
    }
    SetEvent(tsdPtr->socketListLock);
}

2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
SocketCheckProc(
    TCL_UNUSED(ClientData),
    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)) {







|







2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
 *	May queue an event.
 *
 *----------------------------------------------------------------------
 */

static void
SocketCheckProc(
    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)) {
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
    /*
     * 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.
             */

	    len = sizeof(address);
	    newSocket = accept(fds->fd, &(addr.sa), &len);

	    /*
             * 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(); */







|
|





|




|







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
    /*
     * 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.
	     */

	    len = sizeof(address);
	    newSocket = accept(fds->fd, &(addr.sa), &len);

	    /*
	     * 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
	    if (statePtr->acceptEventCount <= 0) {
		CLEAR_BITS(statePtr->readyEvents, FD_ACCEPT);
	    }

	    SetEvent(tsdPtr->socketListLock);

	    /*
             * 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
	 * 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);







|











|







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
	    if (statePtr->acceptEventCount <= 0) {
		CLEAR_BITS(statePtr->readyEvents, FD_ACCEPT);
	    }

	    SetEvent(tsdPtr->socketListLock);

	    /*
	     * 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
	 * 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
    TcpState *statePtr,
    SOCKET socket)
{
    TcpFdList *fds = statePtr->sockets;

    if (fds == NULL) {
	/*
         * Add the first FD.
         */

	statePtr->sockets = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
	fds = statePtr->sockets;
    } else {
	/*
         * Find end of list and append FD.
         */

	while (fds->next != NULL) {
	    fds = fds->next;
	}

	fds->next = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
	fds = fds->next;







|
|





|
|







2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
    TcpState *statePtr,
    SOCKET socket)
{
    TcpFdList *fds = statePtr->sockets;

    if (fds == NULL) {
	/*
	 * Add the first FD.
	 */

	statePtr->sockets = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
	fds = statePtr->sockets;
    } else {
	/*
	 * Find end of list and append FD.
	 */

	while (fds->next != NULL) {
	    fds = fds->next;
	}

	fds->next = (TcpFdList *)Tcl_Alloc(sizeof(TcpFdList));
	fds = fds->next;
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
    SendSelectMessage(tsdPtr, UNSELECT, statePtr);
    SendSelectMessage(tsdPtr, SELECT, statePtr);

    while (1) {
	int event_found;

	/*
         * Get statePtr lock.
         */

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	/*
         * Check if event occured.
         */

	event_found = GOT_BITS(statePtr->readyEvents, events);

	/*
         * Free list lock.
         */

	SetEvent(tsdPtr->socketListLock);

	/*
         * Exit loop if event occured.
         */

	if (event_found) {
	    break;
	}

	/*
         * Exit loop if event did not occur but this is a non-blocking channel
         */

	if (statePtr->flags & TCP_NONBLOCKING) {
	    *errorCodePtr = EWOULDBLOCK;
	    result = 0;
	    break;
	}








|
|




|
|




|
|




|
|






|
|







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
    SendSelectMessage(tsdPtr, UNSELECT, statePtr);
    SendSelectMessage(tsdPtr, SELECT, statePtr);

    while (1) {
	int event_found;

	/*
	 * Get statePtr lock.
	 */

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);

	/*
	 * Check if event occurred.
	 */

	event_found = GOT_BITS(statePtr->readyEvents, events);

	/*
	 * Free list lock.
	 */

	SetEvent(tsdPtr->socketListLock);

	/*
	 * Exit loop if event occurred.
	 */

	if (event_found) {
	    break;
	}

	/*
	 * Exit loop if event did not occur but this is a non-blocking channel
	 */

	if (statePtr->flags & TCP_NONBLOCKING) {
	    *errorCodePtr = EWOULDBLOCK;
	    result = 0;
	    break;
	}

3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
 *	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.
 *
 *----------------------------------------------------------------------
 */

static LRESULT CALLBACK
SocketProc(
    HWND hwnd,







|







3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
 *	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
 *	occurred.
 *
 *----------------------------------------------------------------------
 */

static LRESULT CALLBACK
SocketProc(
    HWND hwnd,
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
}

/*
 *----------------------------------------------------------------------
 *
 * FindFDInList --
 *
 *	Return true, if the given file descriptior is contained in the
 *	file descriptor list.
 *
 * Results:
 *	true if found.
 *
 * Side effects:
 *







|







3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
}

/*
 *----------------------------------------------------------------------
 *
 * FindFDInList --
 *
 *	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
 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
TcpThreadActionProc(
    ClientData 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();
	Tcl_MutexUnlock(&socketMutex);

	tsdPtr = TCL_TSD_INIT(&dataKey);

	WaitForSingleObject(tsdPtr->socketListLock, INFINITE);
	statePtr->nextPtr = tsdPtr->socketList;
	tsdPtr->socketList = statePtr;








|












<
|
<







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
 *	Changes thread local list of valid channels.
 *
 *----------------------------------------------------------------------
 */

static void
TcpThreadActionProc(
    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.
	 */


	TclInitSockets();


	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
/*
 * tclWinTest.c --
 *
 *	Contains commands for platform specific tests on Windows.
 *
 * 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.
 */



#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


/*
 * MinGW 3.4.2 does not define this.
 */
#ifndef INHERITED_ACE
#define INHERITED_ACE (0x10)
#endif





|





>
>













<

<
>







1
2
3
4
5
6
7
8
9
10
11
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 © 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
 */

#include <aclapi.h>

#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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TesteventloopCmd(
    TCL_UNUSED(ClientData),
    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. */







|







97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TesteventloopCmd(
    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
	    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);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







|







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", (char *)NULL);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestvolumetypeCmd(
    TCL_UNUSED(ClientData),
    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];







|







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestvolumetypeCmd(
    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
	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());
	return TCL_ERROR;
    }
    Tcl_AppendResult(interp, volType, NULL);
    return TCL_OK;
#undef VOL_BUF_SIZE
}

/*
 *----------------------------------------------------------------------
 *







|
|


|







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:""), "\"", (char *)NULL);
	Tcl_WinConvertError(GetLastError());
	return TCL_ERROR;
    }
    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
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestwinclockCmd(
    TCL_UNUSED(ClientData),
    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 */







|







239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
 *	None.
 *
 *----------------------------------------------------------------------
 */

static int
TestwinclockCmd(
    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
    Tcl_SetObjResult(interp, result);

    return TCL_OK;
}

static int
TestwinsleepCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp* interp,		/* Tcl interpreter */
    int objc,			/* Parameter count */
    Tcl_Obj *const * objv)	/* Parameter vector */
{
    int ms;

    if (objc != 2) {







|







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(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
 *	This Tcl process closes, hard... Bang!
 *
 *----------------------------------------------------------------------
 */

static int
TestExceptionCmd(
    TCL_UNUSED(ClientData),
    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",







|







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(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

    /* SMASH! */
    RaiseException(exceptions[cmd], EXCEPTION_NONCONTINUABLE, 0, NULL);

    return TCL_OK;
}





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).


     */














    const BOOL set_readOnly = !(pmode & 0222);




    BOOL acl_readOnly_found = FALSE, curAclPresent, curAclDefaulted;
    SID_IDENTIFIER_AUTHORITY userSidAuthority = {
	SECURITY_WORLD_SID_AUTHORITY


    };


    BYTE *secDesc = 0;


    DWORD secDescLen, attr, newAclSize;
    ACL_SIZE_INFORMATION ACLSize;
    PACL curAcl, newAcl = 0;

    WORD j;

    SID *userSid = 0;
    char *userDomain = 0;
    int res = 0;



    /*

     * Process the chmod request.

     */



    attr = GetFileAttributesA(nativePath);

    /*


     * nativePath not found
     */

    if (attr == 0xFFFFFFFF) {
	res = -1;

	goto done;
    }







    /*
     * If nativePath is not a directory, there is no special handling.

     */

    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
	goto done;




    }

    /*
     * Set the result to error, if the ACL change is successful it will be
     * reset to 0.
     */


    res = -1;



    /*
     * 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;





	if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
	    goto done;
	}






	secDesc = (BYTE *)Tcl_Alloc(secDescLen);
	if (!GetFileSecurityA(nativePath, infoBits,
		(PSECURITY_DESCRIPTOR) secDesc, secDescLen, &secDescLen2)
		|| (secDescLen < secDescLen2)) {



	    goto done;
	}

    }


    /*

     * Get the World SID.
     */


    userSid = (SID *)Tcl_Alloc(GetSidLengthRequired((UCHAR) 1));
    InitializeSid(userSid, &userSidAuthority, (BYTE) 1);
    *(GetSidSubAuthority(userSid, 0)) = SECURITY_WORLD_RID;








    /*
     * 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;
    } else if (!GetAclInformation(curAcl, &ACLSize, sizeof(ACLSize),
	    AclSizeInformation)) {

	goto done;
    }


    /*
     * Allocate memory for the new ACL.
     */




    newAclSize = ACLSize.AclBytesInUse + sizeof(ACCESS_DENIED_ACE)






	    + GetLengthSid(userSid) - sizeof(DWORD);
    newAcl = (PACL) Tcl_Alloc(newAclSize);

    /*
     * Initialize the new ACL.
     */







    if (!InitializeAcl(newAcl, newAclSize, ACL_REVISION)) {
	goto done;
    }

    /*
     * Add denied to make readonly, this will be known as a "read-only tag".
     */

    if (set_readOnly && !AddAccessDeniedAce(newAcl, ACL_REVISION,
	    readOnlyMask, userSid)) {
	goto done;
    }

    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*/,
	    NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) {
	res = 0;
    }

  done:
    if (secDesc) {
	Tcl_Free(secDesc);



    }
    if (newAcl) {
	Tcl_Free(newAcl);
    }
    if (userSid) {
	Tcl_Free(userSid);
    }
    if (userDomain) {
	Tcl_Free(userDomain);
    }

    if (res != 0) {
	return res;
    }

    /*
     * Run normal chmod command.
     */

    return chmod(nativePath, pmode);
}

/*
 *---------------------------------------------------------------------------
 *
 * TestchmodCmd --







>
>
>
>





<
<
<
<
<
<
<
<

<
>
>

>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
>
|
<
|
>
>
|
>
>
|
>
>
|
|
<
>
|
>
|
|
|

>
>
|
>
|
>
|
>
>
|
<

|
>
>
|
<
|
<
|
>


>
>
>
>
>
>
|

<
>

|
|
<
>
>
>
>
|
|
<
<
<
<
>
|
<
>
>
|
<
<
<
<
|
>
|
>
>
|
>

>
>
>
|


>
>
>
>
|
>
|
<
<
<
>
>
>


>
|
>

<
>
|
<
>
|
<
<
<
>
>
>
>
>
>
>
|
<
<
<

|
>
>
|
|
|
|
|
|
<
|
>
|
|
>

<
|
|
>
>
>
|
<
>
>
>
>
>
>
|
<
|
|
|
|
>
>
>
>
>
|
>




<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<









<
|
|





|
|
>
>
>




|
|
<
<
<






<
|
<
<







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)
{








    /*

     * 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;
    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;


    DWORD attr, newAclSize;
    PACL newAcl = NULL;
    int res = 0;

    HANDLE hToken = NULL;
    int i;
    int nSids = 0;
    struct {
	PSID pSid;
	DWORD mask;
	DWORD sidLen;

    } aceEntry[3];
    DWORD dw;
    int isDir;
    TOKEN_USER *pTokenUser = NULL;

    res = -1; /* Assume failure */

    attr = GetFileAttributesA(nativePath);
    if (attr == 0xFFFFFFFF) {
	goto done; /* Not found */
    }

    isDir = (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
	goto done;
    }


    /* Get process SID */
    if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &dw)
	    && GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
	goto done;

    }

    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 = 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;
    }
    /*

     * Always include DACL modify rights so we don't get locked out
     */
    aceEntry[nSids].mask = READ_CONTROL | WRITE_DAC | WRITE_OWNER | SYNCHRONIZE |
			   FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;

    if (pmode & 0700) {
	/* Owner permissions. Assumes current process is owner */
	if (pmode & 0400) {
	    aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
	}
	if (pmode & 0200) {




	    aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
	}

	if (pmode & 0100) {
	    aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
	}




    }
    ++nSids;

    if (pmode & 0070) {
	/* Group permissions. */

	TOKEN_PRIMARY_GROUP *pTokenGroup;

	/* Get primary group SID */
	if (!GetTokenInformation(
		hToken, TokenPrimaryGroup, NULL, 0, &dw) &&
		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;
	}
	aceEntry[nSids].sidLen = GetLengthSid(pTokenGroup->PrimaryGroup);
	aceEntry[nSids].pSid = Tcl_Alloc(aceEntry[nSids].sidLen);



	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 */


	aceEntry[nSids].mask = 0;
	if (pmode & 0040) {

	    aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
	}



	if (pmode & 0020) {
	    aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
	}
	if (pmode & 0010) {
	    aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
	}
	++nSids;
    }




    if (pmode & 0007) {
	/* World permissions */
	PSID pWorldSid;
	if (!ConvertStringSidToSidA("S-1-1-0", &pWorldSid)) {
	    goto done;
	}
	aceEntry[nSids].sidLen = GetLengthSid(pWorldSid);
	aceEntry[nSids].pSid = Tcl_Alloc(aceEntry[nSids].sidLen);
	if (!CopySid(aceEntry[nSids].sidLen, aceEntry[nSids].pSid, pWorldSid)) {

	    LocalFree(pWorldSid);
	    Tcl_Free(aceEntry[nSids].pSid); /* Since we have not ++'ed nSids */
	    goto done;
	}
	LocalFree(pWorldSid);


	/* Generate mask for world ACL */

	aceEntry[nSids].mask = 0;
	if (pmode & 0004) {
	    aceEntry[nSids].mask |= isDir ? dirReadMask : fileReadMask;
	}

	if (pmode & 0002) {
	    aceEntry[nSids].mask |= isDir ? dirWriteMask : fileWriteMask;
	}
	if (pmode & 0001) {
	    aceEntry[nSids].mask |= isDir ? dirExecuteMask : fileExecuteMask;
	}
	++nSids;

    }

    /* 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;
    }




    for (i = 0; i < nSids; ++i) {




	if (!AddAccessAllowedAce(newAcl, ACL_REVISION, aceEntry[i].mask, aceEntry[i].pSid)) {








































	    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 (SetNamedSecurityInfoA((LPSTR)nativePath, SE_FILE_OBJECT,
	    DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
	    NULL, NULL, newAcl, NULL) == ERROR_SUCCESS) {
	res = 0;
    }

  done:
    if (pTokenUser) {
	Tcl_Free(pTokenUser);
    }
    if (hToken) {
	CloseHandle(hToken);
    }
    if (newAcl) {
	Tcl_Free(newAcl);
    }
    for (i = 0; i < nSids; ++i) {
	Tcl_Free(aceEntry[i].pSid);



    }

    if (res != 0) {
	return res;
    }


    /* Run normal chmod command */


    return chmod(nativePath, pmode);
}

/*
 *---------------------------------------------------------------------------
 *
 * TestchmodCmd --
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
 *	Changes permissions of specified files.
 *
 *---------------------------------------------------------------------------
 */

static int
TestchmodCmd(
    TCL_UNUSED(ClientData),
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Parameter count */
    Tcl_Obj *const * objv)	/* Parameter vector */
{
    int i, mode;

    if (objc < 2) {







|







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(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

	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);
	    return TCL_ERROR;
	}
	Tcl_DStringFree(&buffer);
    }
    return TCL_OK;
}








|







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),
		    (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
/*
 * 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
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclWinInt.h"






|
|
|







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 © 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
 * 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.
 */

#if TCL_THREADS

static struct Tcl_Mutex_ {
    CRITICAL_SECTION crit;
} allocLock;







|







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 dynamically allocated storage.
 */

#if TCL_THREADS

static struct Tcl_Mutex_ {
    CRITICAL_SECTION crit;
} allocLock;
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
 *----------------------------------------------------------------------
 */

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. */
    int flags)			/* Flags controlling behaviour of the new
				 * thread. */
{
    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
		 */

#if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__)
    tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize,
	    (Tcl_ThreadCreateProc*) TclWinThreadStart, winThreadPtr,
	    0, (unsigned *)idPtr);
#else
    tHandle = CreateThread(NULL, (DWORD) stackSize,
	    TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr);
#endif

    if (tHandle == NULL) {
	LeaveCriticalSection(&joinLock);
	return TCL_ERROR;
    } else {







|




|










|
<

|
|



|







199
200
201
202
203
204
205
206
207
208
209
210
211
212
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. */
    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 */
    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 */


#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,
	    TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr);
#endif

    if (tHandle == NULL) {
	LeaveCriticalSection(&joinLock);
	return TCL_ERROR;
    } else {
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
TclpThreadExit(
    int status)
{
    EnterCriticalSection(&joinLock);
    TclSignalExitThread(Tcl_GetCurrentThread(), status);
    LeaveCriticalSection(&joinLock);

#if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__)
    _endthreadex((unsigned) status);
#else
    ExitThread((DWORD) status);
#endif
}

/*







|







295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
TclpThreadExit(
    int status)
{
    EnterCriticalSection(&joinLock);
    TclSignalExitThread(Tcl_GetCurrentThread(), status);
    LeaveCriticalSection(&joinLock);

#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
 *
 *----------------------------------------------------------------------
 */

Tcl_ThreadId
Tcl_GetCurrentThread(void)
{
    return (Tcl_ThreadId)(size_t)GetCurrentThreadId();
}

/*
 *----------------------------------------------------------------------
 *
 * TclpInitLock
 *







|







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
 *
 *----------------------------------------------------------------------
 */

Tcl_ThreadId
Tcl_GetCurrentThread(void)
{
    return (Tcl_ThreadId)INT2PTR(GetCurrentThreadId());
}

/*
 *----------------------------------------------------------------------
 *
 * TclpInitLock
 *
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468

/*
 *----------------------------------------------------------------------
 *
 * 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
 *	all other locks are allocated...
 *
 * Results:
 *	A pointer to a mutex that is suitable for passing to Tcl_MutexLock and
 *	Tcl_MutexUnlock.
 *
 * Side effects:







|







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 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

    DeleteCriticalSection(&initLock);
}

#if TCL_THREADS

/* locally used prototype */
static void		FinalizeConditionEvent(ClientData data);

/*
 *----------------------------------------------------------------------
 *
 * Tcl_MutexLock --
 *
 *	This procedure is invoked to lock a mutex. This is a self initializing







|







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(void *data);

/*
 *----------------------------------------------------------------------
 *
 * Tcl_MutexLock --
 *
 *	This procedure is invoked to lock a mutex. This is a self initializing
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
	TclpGlobalUnlock();
    }
    csPtr = *((CRITICAL_SECTION **)mutexPtr);
    winCondPtr = *((WinCondition **)condPtr);
    if (timePtr == NULL) {
	wtime = INFINITE;
    } else {
	wtime = timePtr->sec * 1000 + timePtr->usec / 1000;
    }

    /*
     * Queue the thread on the condition, using the per-condition lock for
     * serialization.
     */








|







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 = (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
     */

    if (timeout) {
	if (tsdPtr->flags & WIN_THREAD_RUNNING) {
	    timeout = 0;
	} else {
	    /*
	     * When dequeuing, 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
	     * later.
	     */

	    if (winCondPtr->firstPtr == tsdPtr) {
		winCondPtr->firstPtr = tsdPtr->nextPtr;
	    } else {
		tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr;







|

|







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 dequeueing, we can leave the tsdPtr->nextPtr and
	     * tsdPtr->prevPtr with dangling pointers because they are
	     * 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
 *	The per-thread event is closed.
 *
 *----------------------------------------------------------------------
 */

static void
FinalizeConditionEvent(
    ClientData data)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) data;

    tsdPtr->flags = WIN_THREAD_UNINIT;
    CloseHandle(tsdPtr->condEvent);
}








|







875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
 *	The per-thread event is closed.
 *
 *----------------------------------------------------------------------
 */

static void
FinalizeConditionEvent(
    void *data)
{
    ThreadSpecificData *tsdPtr = (ThreadSpecificData *) data;

    tsdPtr->flags = WIN_THREAD_UNINIT;
    CloseHandle(tsdPtr->condEvent);
}


Changes to win/tclWinTime.c.

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.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"







|







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 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

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) */

    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
				 * tell the calibration loop to terminate. */







|
>







24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

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) */
    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
				 * tell the calibration loop to terminate. */
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

















129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
    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];
				/* Last 64 samples of system time. */
    Tcl_WideInt 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,
    (ULARGE_INTEGER) (DWORDLONG) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
    (LARGE_INTEGER) (Tcl_WideInt) 0,
#else
    {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 */

    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 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		NativeScaleTime(Tcl_Time* timebuf,
			    ClientData clientData);
static Tcl_WideInt	NativeGetMicroseconds(void);
static void		NativeGetTime(Tcl_Time* timebuf,
			    ClientData clientData);

/*
 * TIP #233 (Virtualized Time): Data for the time hooks, if any.
 */

Tcl_GetTimeProc *tclGetTimeProcPtr = NativeGetTime;
Tcl_ScaleTimeProc *tclScaleTimeProcPtr = NativeScaleTime;
ClientData tclTimeClientData = NULL;


















/*
 *----------------------------------------------------------------------
 *
 * 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
TclpGetSeconds(void)
{
    Tcl_WideInt usecSincePosixEpoch;


    /* Try to use high resolution timer */

    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
    ) {
	return usecSincePosixEpoch / 1000000;
    } else {
	Tcl_Time t;

	tclGetTimeProcPtr(&t, tclTimeClientData);	/* Tcl_GetTime inlined. */
	return t.sec;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetClicks --







|

|













|

|
|
|


















|
>








|


|
|
|
|

|
|

|







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


















|


|

>
|
>
|
|
<




|
|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
186
187
188
    LARGE_INTEGER posixEpoch;	/* Posix epoch expressed as 100-ns ticks since
				 * the windows epoch. */

    /*
     * Data used in developing the estimate of performance counter frequency
     */

    unsigned long long fileTimeSample[SAMPLES];
				/* Last 64 samples of system time. */
    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) (long long) 0,
    (ULARGE_INTEGER) (DWORDLONG) 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},
#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 */
    double microsecsScale;	/* Denominator scale between clock / microsecs */
} wideClick = {0, 0, 0.0};


/*
 * Declarations for functions defined later in this file.
 */

static void		StopCalibration(void *clientData);
static DWORD WINAPI	CalibrationThread(LPVOID arg);
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,
			    void *clientData);
static long long	NativeGetMicroseconds(void);
static void		NativeGetTime(Tcl_Time* timebuf,
			    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.
 *
 *----------------------------------------------------------------------
 */

unsigned long long
TclpGetSeconds(void)
{
    long long usecSincePosixEpoch;

    /*
     * Try to use high resolution timer
     */

    if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) {

	return usecSincePosixEpoch / 1000000;
    } else {
	Tcl_Time t;

	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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideUInt
TclpGetClicks(void)
{
    Tcl_WideInt usecSincePosixEpoch;


    /* Try to use high resolution timer */

    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
    ) {
	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;

    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclpGetWideClicks --







|


|

>
|
>
|
|
<
|








|
|
>







197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213

214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

unsigned long long
TclpGetClicks(void)
{
    long long usecSincePosixEpoch;

    /*
     * Try to use high resolution timer.
     */

    if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) {

	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 */

	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
 *	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
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;
	}
	/* fallback using microseconds */
	wideClick.perfCounter = 0;
	wideClick.microsecsScale = 1;
	return TclpGetMicroseconds();
    } else {
    	return TclpGetMicroseconds();







|












>













|







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
 *	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).
 *
 *----------------------------------------------------------------------
 */

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 (long long)curCounter.QuadPart;
	}
	/* fallback using microseconds */
	wideClick.perfCounter = 0;
	wideClick.microsecsScale = 1;
	return TclpGetMicroseconds();
    } else {
    	return TclpGetMicroseconds();
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
 *----------------------------------------------------------------------
 */

double
TclpWideClickInMicrosec(void)
{
    if (!wideClick.initialized) {
    	(void)TclpGetWideClicks();	/* initialize */
    }
    return wideClick.microsecsScale;
}

/*
 *----------------------------------------------------------------------
 *







|







301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
 *----------------------------------------------------------------------
 */

double
TclpWideClickInMicrosec(void)
{
    if (!wideClick.initialized) {
    	(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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

Tcl_WideInt
TclpGetMicroseconds(void)
{
    Tcl_WideInt usecSincePosixEpoch;


    /* Try to use high resolution timer */

    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
    ) {
	return usecSincePosixEpoch;
    } else {
	/*
	* 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;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetTime --







|


|

>
|
>
|
|
<



|
|
|



|
|







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
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

long long
TclpGetMicroseconds(void)
{
    long long usecSincePosixEpoch;

    /*
     * 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.
	 */

	Tcl_Time now;

	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
 *----------------------------------------------------------------------
 */

void
Tcl_GetTime(
    Tcl_Time *timePtr)		/* Location to store time information. */
{
    Tcl_WideInt usecSincePosixEpoch;


    /* Try to use high resolution timer */

    if ( tclGetTimeProcPtr == NativeGetTime
      && (usecSincePosixEpoch = NativeGetMicroseconds())
    ) {
	timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
	timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
    } else {
    	tclGetTimeProcPtr(timePtr, tclTimeClientData);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NativeScaleTime --







|

>
|
>
|
|
<
|
|

|







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
 *----------------------------------------------------------------------
 */

void
Tcl_GetTime(
    Tcl_Time *timePtr)		/* Location to store time information. */
{
    long long usecSincePosixEpoch;

    /*
     * Try to use high resolution timer.
     */

    if (IsTimeNative() && (usecSincePosixEpoch = NativeGetMicroseconds())) {

	timePtr->sec = usecSincePosixEpoch / 1000000;
	timePtr->usec = usecSincePosixEpoch % 1000000;
    } else {
	GetTime(timePtr);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * NativeScaleTime --
382
383
384
385
386
387
388
389
390
391
392
393
394


























































































395
396
397
398
399
400
401
 *
 *----------------------------------------------------------------------
 */

static void
NativeScaleTime(
    TCL_UNUSED(Tcl_Time *),
    TCL_UNUSED(ClientData))
{
    /*
     * Native scale is 1:1. Nothing is done.
     */
}



























































































/*
 *----------------------------------------------------------------------
 *
 * NativeGetMicroseconds --
 *
 *	Gets the current system time in microseconds since the beginning







|





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
 *
 *----------------------------------------------------------------------
 */

static void
NativeScaleTime(
    TCL_UNUSED(Tcl_Time *),
    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
 *	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
NativeCalc100NsTicks(
    ULONGLONG fileTimeLastCall,
    LONGLONG perfCounterLastCall,
    LONGLONG curCounterFreq,
    LONGLONG curCounter
) {

    return fileTimeLastCall +
	((curCounter - perfCounterLastCall) * 10000000 / curCounterFreq);
}

static Tcl_WideInt
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) {
		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);







|




|
<
>

|


|












<



<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|







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
 *	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 long long
NativeCalc100NsTicks(
    ULONGLONG fileTimeLastCall,
    LONGLONG perfCounterLastCall,
    LONGLONG curCounterFreq,
    LONGLONG curCounter)

{
    return fileTimeLastCall +
	    ((curCounter - perfCounterLastCall) * 10000000 / curCounterFreq);
}

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;




	    /*
































































	     * If the performance counter is available, start a thread to
	     * calibrate it.
	     */

	    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
	/*
	 * Query the performance counter and use it to calculate the current
	 * time.
	 */

	ULONGLONG fileTimeLastCall;
	LONGLONG perfCounterLastCall, curCounterFreq;
				/* 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 */


	    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
	) {

	    /* Calibrated file-time is saved from posix in 100-ns ticks */


	    return NativeCalc100NsTicks(fileTimeLastCall,
		perfCounterLastCall, curCounterFreq, curCounter.QuadPart) / 10;

	}
    }

    /*
     * High resolution timer is not available.
     */

    return 0;
}

/*
 *----------------------------------------------------------------------
 *
 * NativeGetTime --







|
|








>











>

>
|
>
>














|
<
>
|
>
>

|
>






>







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
	/*
	 * Query the performance counter and use it to calculate the current
	 * time.
	 */

	ULONGLONG fileTimeLastCall;
	LONGLONG perfCounterLastCall, curCounterFreq;
				/* 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
	     */

	    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) {

	    /*
	     * Calibrated file-time is saved from Posix in 100-ns ticks.
	     */

	    return NativeCalc100NsTicks(fileTimeLastCall,
		    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
 *
 *----------------------------------------------------------------------
 */

static void
NativeGetTime(
    Tcl_Time *timePtr,
    TCL_UNUSED(ClientData))
{
    Tcl_WideInt usecSincePosixEpoch;

    /*
     * Try to use high resolution timer.
     */

    if ( (usecSincePosixEpoch = NativeGetMicroseconds()) ) {

	timePtr->sec = (long) (usecSincePosixEpoch / 1000000);
	timePtr->usec = (unsigned long) (usecSincePosixEpoch % 1000000);
    } else {
	/*
	* High resolution timer is not available. Just use ftime.
	*/

	struct _timeb t;

	_ftime(&t);
	timePtr->sec = (long)t.time;
	timePtr->usec = t.millitm * 1000;
    }
}

/*
 *----------------------------------------------------------------------
 *







|

|




>
|
>
|
|


|
|




|







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
 *
 *----------------------------------------------------------------------
 */

static void
NativeGetTime(
    Tcl_Time *timePtr,
    TCL_UNUSED(void *))
{
    long long usecSincePosixEpoch;

    /*
     * Try to use high resolution timer.
     */

    usecSincePosixEpoch = NativeGetMicroseconds();
    if (usecSincePosixEpoch) {
	timePtr->sec = usecSincePosixEpoch / 1000000;
	timePtr->usec = usecSincePosixEpoch % 1000000;
    } else {
	/*
	 * High resolution timer is not available. Just use ftime.
	 */

	struct _timeb t;

	_ftime(&t);
	timePtr->sec = t.time;
	timePtr->usec = t.millitm * 1000;
    }
}

/*
 *----------------------------------------------------------------------
 *
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
 *----------------------------------------------------------------------
 */

void TclWinResetTimerResolution(void);

static void
StopCalibration(
    TCL_UNUSED(ClientData))
{
    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.
     */







|







720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
 *----------------------------------------------------------------------
 */

void TclWinResetTimerResolution(void);

static void
StopCalibration(
    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
     */

    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 */


    timeInfo.fileTimeLastCall.QuadPart -= timeInfo.posixEpoch.QuadPart;

    ResetCounterSamples(timeInfo.fileTimeLastCall.QuadPart,
	    timeInfo.perfCounterLastCall.QuadPart,
	    timeInfo.curCounterFreq.QuadPart);

    /*







>
>
|
>
>







776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
     */

    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.
     */

    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
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 */

    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
				 * time. */
    Tcl_WideInt driftFreq;	/* Frequency needed to drift virtual time into
				 * step over 1 second. */

    /*
     * 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)
    ) {

    	/* again in next one second */


	return;
    }
    QueryPerformanceCounter(&curPerfCounter);

    lastFileTime.QuadPart = curFileTime.QuadPart;

    /*
     * We devide 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.
     */








|
>


|
|
|
|

|



|






>
>
|
>
|
|
|
<
>
|
>
>







|







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
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 */
    LARGE_INTEGER curFileTime;	/* File time at the time this callback was
				 * scheduled. */
    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. */
    long long driftFreq;	/* Frequency needed to drift virtual time into
				 * step over 1 second. */

    /*
     * 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)) {

    	/*
	 * Look again in next one second.
	 */

	return;
    }
    QueryPerformanceCounter(&curPerfCounter);

    lastFileTime.QuadPart = curFileTime.QuadPart;

    /*
     * 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
     * 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);

    /*
     * 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);

    /*
     * 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;
    } else {

    	/* 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
	 */

	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;

    }


    /* 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;
	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)

	 */

	LARGE_INTEGER newPerfCounter;
	Tcl_WideInt nt0, nt1;

	QueryPerformanceCounter(&newPerfCounter);
	nt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.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) */



	    vt0 += nt0 - nt1;


	    /* 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;
	    }
	}
    }


    /* 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) */


    if (tdiff < -100000 || tdiff > 100000) {

	/* 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;







|



















|
|
>








>
|
>
>


>
|
>
>


>

|
|
|

>







>
|
>


>
|
>
>
|
|

|
|



|
|
|
>

>

|



|
|

|
|
>
|
>
|
>
>
>

>
>
|
>
>
>


>
|
>
>





>
|
>
>


>
|
>
>

>
|
>
>







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
     * 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,
	    (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);

    /*
     * 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;
    } else {
    	/*
	 * 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
	 */

	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;
    }

    /*
     * 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;
	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).
	 */

	LARGE_INTEGER newPerfCounter;
	long long nt0, nt1;

	QueryPerformanceCounter(&newPerfCounter);
	nt0 = NativeCalc100NsTicks(timeInfo.fileTimeLastCall.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).
	     */

	    vt0 += nt0 - nt1;

	    /*
	     * 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;
	    }
	}
    }

    /*
     * 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)
     */

    if (tdiff < -100000 || tdiff > 100000) {
	/*
	 * 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
 *	given frequency.
 *
 *----------------------------------------------------------------------
 */

static void
ResetCounterSamples(
    Tcl_WideUInt fileTime,	/* Current file time */
    Tcl_WideInt perfCounter,	/* Current performance counter */
    Tcl_WideInt perfFreq)	/* Target performance frequency */
{
    int i;
    for (i=SAMPLES-1 ; i>=0 ; --i) {

	timeInfo.perfCounterSample[i] = perfCounter;
	timeInfo.fileTimeSample[i] = fileTime;
	perfCounter -= perfFreq;
	fileTime -= 10000000;
    }
    timeInfo.sampleNo = 0;
}







|
|
|


|
>







1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
 *	given frequency.
 *
 *----------------------------------------------------------------------
 */

static void
ResetCounterSamples(
    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) {
	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
 *
 * 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
AccumulateSample(
    Tcl_WideInt perfCounter,
    Tcl_WideUInt fileTime)
{

    Tcl_WideUInt workFTSample;	/* File time sample being removed from or
				 * added to the circular buffer. */
    Tcl_WideInt workPCSample;	/* Performance counter sample being removed
				 * from or added to the circular buffer. */

    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 */

    /*
     * Test for jumps and reset the samples if we have one.
     */

    if (timeInfo.sampleNo == 0) {
	lastPCSample =







|

|
|

>
|

|

>
|
|
|
|
|







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
 *
 * 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 long long
AccumulateSample(
    long long perfCounter,
    unsigned long long fileTime)
{
    unsigned long long workFTSample;
				/* File time sample being removed from or
				 * added to the circular buffer. */
    long long workPCSample;	/* Performance counter sample being removed
				 * from or added to the circular buffer. */
    unsigned long long lastFTSample;
				/* 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
	 */

	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;

	/*
	 * Advance the sample number.
	 */

	if (++timeInfo.sampleNo >= SAMPLES) {
	    timeInfo.sampleNo = 0;







|







1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
	 */

	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] = (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
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    ClientData clientData)
{
    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;
}

/*







|







1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
 *----------------------------------------------------------------------
 */

void
Tcl_SetTimeProc(
    Tcl_GetTimeProc *getProc,
    Tcl_ScaleTimeProc *scaleProc,
    void *clientData)
{
    tclGetTimeProcPtr = getProc;
    tclScaleTimeProcPtr = scaleProc;
    tclTimeClientData = clientData;
}

/*
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
 *----------------------------------------------------------------------
 */

void
Tcl_QueryTimeProc(
    Tcl_GetTimeProc **getProc,
    Tcl_ScaleTimeProc **scaleProc,
    ClientData *clientData)
{
    if (getProc) {
	*getProc = tclGetTimeProcPtr;
    }
    if (scaleProc) {
	*scaleProc = tclScaleTimeProcPtr;
    }







|







1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
 *----------------------------------------------------------------------
 */

void
Tcl_QueryTimeProc(
    Tcl_GetTimeProc **getProc,
    Tcl_ScaleTimeProc **scaleProc,
    void **clientData)
{
    if (getProc) {
	*getProc = tclGetTimeProcPtr;
    }
    if (scaleProc) {
	*scaleProc = tclScaleTimeProcPtr;
    }

Changes to win/tclooConfig.sh.

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







|
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.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
	    <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:application>
    <dependency>
	<dependentAssembly>
	    <assemblyIdentity
		    type="win32"
		    name="Microsoft.Windows.Common-Controls"
		    version="6.0.0.0"







<
<







>
>
>
>







24
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}"/>


	</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.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
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 "ProductName", "Tcl " TCL_VERSION " for Windows\0"
            VALUE "ProductVersion", TCL_PATCH_LEVEL
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x409, 1200







<

|







40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
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 "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

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/x86_64-w64-mingw32-nmakehlp.exe.

cannot compute difference between binary files